From 4b529477b0ac8a165bbfe68190fe3dc2ddeff62c Mon Sep 17 00:00:00 2001 From: Cuynu <90895715+cuynu@users.noreply.github.com> Date: Fri, 23 Dec 2022 18:38:49 +0700 Subject: [PATCH] Delete old --- .gitignore | 120 ---- .idea/.gitignore | 9 - .idea/discord.xml | 7 - .idea/git_toolbox_prj.xml | 15 - .idea/misc.xml | 8 - .idea/vcs.xml | 12 - .releaserc | 43 -- LICENSE | 674 ------------------ build.gradle.kts | 66 -- gradle.properties | 2 - gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 0 bytes gradle/wrapper/gradle-wrapper.properties | 5 - gradlew | 185 ----- gradlew.bat | 89 --- patches.json | 1 - settings.gradle.kts | 1 - .../app/revanced/extensions/Extensions.kt | 201 ------ src/main/kotlin/app/revanced/meta/Meta.kt | 27 - .../app/revanced/meta/json/Generator.kt | 50 -- .../app/revanced/meta/json/JsonPatch.kt | 27 - .../app/revanced/meta/readme/Extensions.kt | 10 - .../app/revanced/meta/readme/Generator.kt | 42 -- .../revanced/meta/readme/SemanticVersion.kt | 22 - .../app/revanced/meta/readme/Template.kt | 12 - .../SubscriptionUnlockCompatibility.kt | 13 - .../SubscriptionUnlockFingerprint.kt | 16 - .../patch/SubscriptionUnlockPatch.kt | 47 -- .../annotations/HexEditorAdsCompatibility.kt | 13 - .../ad/fingerprints/PrimaryAdsFingerprint.kt | 15 - .../hexeditor/ad/patch/HexEditorAdsPatch.kt | 39 - .../pro/annotations/UnlockProCompatibility.kt | 9 - .../pro/fingerprints/CheckProFingerprint.kt | 14 - .../misc/pro/patch/UnlockProPatch.kt | 38 - .../annotations/MusicVideoAdsCompatibility.kt | 13 - ...ShowMusicVideoAdsConstructorFingerprint.kt | 34 - .../ShowMusicVideoAdsFingerprint.kt | 22 - .../ad/video/patch/MusicVideoAdsPatch.kt | 40 -- .../annotations/CodecsUnlockCompatibility.kt | 13 - .../AllCodecsReferenceFingerprint.kt | 57 -- .../fingerprints/CodecsLockFingerprint.kt | 34 - .../audio/codecs/patch/CodecsUnlockPatch.kt | 56 -- .../ExclusiveAudioCompatibility.kt | 13 - .../AudioOnlyEnablerFingerprint.kt | 38 - .../fingerprints/ExclusiveAudioFingerprint.kt | 56 -- .../patch/ExclusiveAudioPatch.kt | 33 - .../annotations/CompactHeaderCompatibility.kt | 13 - .../CompactHeaderConstructorFingerprint.kt | 29 - .../compactheader/patch/CompactHeaderPatch.kt | 41 -- .../MinimizedPlaybackCompatibility.kt | 13 - .../MinimizedPlaybackManagerFingerprint.kt | 32 - .../patch/MinimizedPlaybackPatch.kt | 34 - .../HideGetPremiumCompatibility.kt | 13 - .../fingerprints/HideGetPremiumFingerprint.kt | 22 - .../HideGetPremiumParentFingerprint.kt | 25 - .../premium/patch/HideGetPremiumPatch.kt | 51 -- .../RemoveTasteBuilderCompatibility.kt | 18 - .../TasteBuilderConstructorFingerprint.kt | 39 - .../patch/RemoveTasteBuilderPatch.kt | 41 -- .../RemoveUpgradeButtonCompatibility.kt | 13 - .../PivotBarConstructorFingerprint.kt | 67 -- .../patch/RemoveUpgradeButtonPatch.kt | 78 -- .../MusicMicroGPatchCompatibility.kt | 13 - .../CastContextFetchFingerprint.kt | 15 - .../CastDynamiteModuleFingerprint.kt | 15 - .../CastDynamiteModuleV2Fingerprint.kt | 15 - .../GooglePlayUtilityFingerprint.kt | 26 - .../microg/fingerprints/PrimeFingerprint.kt | 15 - .../fingerprints/ServiceCheckFingerprint.kt | 20 - .../bytecode/MusicMicroGBytecodePatch.kt | 65 -- .../resource/MusicMicroGResourcePatch.kt | 41 -- .../music/misc/microg/shared/Constants.kt | 9 - .../BackgroundPlayCompatibility.kt | 13 - .../BackgroundPlaybackDisableFingerprint.kt | 48 -- .../patch/BackgroundPlayPatch.kt | 36 - .../pro/annotations/UnlockProCompatibility.kt | 9 - .../pro/fingerprints/CheckProFingerprint.kt | 15 - .../nyx/misc/pro/patch/UnlockProPatch.kt | 38 - .../annotations/GeneralAdsCompatibility.kt | 9 - .../ad/general/patch/GeneralAdsPatch.kt | 54 -- .../annotations/PremiumIconCompatibility.kt | 9 - .../fingerprints/PremiumIconFingerprint.kt | 16 - .../premiumicon/patch/PremiumIconPatch.kt | 36 - .../DisableCaptureRestrictionCompatibility.kt | 12 - .../DisableCaptureRestrictionBytecodePatch.kt | 86 --- ...aptureRestrictionAudioDriverFingerprint.kt | 17 - .../DisableCaptureRestrictionResourcePatch.kt | 33 - .../theme/annotations/ThemeCompatibility.kt | 9 - .../spotify/layout/theme/patch/ThemePatch.kt | 66 -- .../PremiumNavbarTabCompatibility.kt | 9 - .../AddPremiumNavbarTabFingerprint.kt | 13 - .../AddPremiumNavbarTabParentFingerprint.kt | 13 - .../patch/PremiumNavbarTabPatch.kt | 63 -- .../annotations/UnlockThemesCompatibility.kt | 9 - .../CheckLockedThemesFingerprint.kt | 15 - .../fingerprints/SetThemeFingerprint.kt | 15 - .../themeunlock/patch/UnlockThemePatch.kt | 43 -- .../ad/annotations/TiktokAdsCompatibility.kt | 14 - .../ConvertHelpFeedItemListFingerprint.kt | 16 - .../FeedItemListCloneFingerprint.kt | 15 - .../patches/tiktok/ad/patch/TiktokAdsPatch.kt | 57 -- .../annotations/FeedFilterCompatibility.kt | 14 - .../FeedApiServiceLIZFingerprint.kt | 18 - .../feedfilter/patch/TiktokFeedFilter.kt | 51 -- .../annotations/DownloadsCompatibility.kt | 14 - .../fingerprints/ACLCommonShareFingerprint.kt | 20 - .../ACLCommonShareFingerprint2.kt | 20 - .../ACLCommonShareFingerprint3.kt | 20 - .../DownloadPathParentFingerprint.kt | 21 - .../downloads/patch/DownloadsPatch.kt | 131 ---- .../annotations/SeekbarCompatibility.kt | 14 - .../AwemeGetVideoControlFingerprint.kt | 18 - .../seekbar/patch/TiktokSeekbarPatch.kt | 47 -- .../speed/annotations/SpeedCompatibility.kt | 14 - .../SpeedControlParentFingerprint.kt | 22 - .../interaction/speed/patch/SpeedPatch.kt | 48 -- .../DisableForceLoginCompatibility.kt | 14 - .../MandatoryLoginServiceFingerprint.kt | 16 - .../MandatoryLoginServiceFingerprint2.kt | 16 - .../patch/DisableForceLoginPatch.kt | 43 -- .../TikTokIntegrationsCompatibility.kt | 14 - .../fingerprints/InitFingerprint.kt | 16 - .../patch/TikTokIntegrationsPatch.kt | 38 - .../TikTokSettingsCompatibility.kt | 14 - .../AdPersonalizationActivityFingerprint.kt | 16 - .../CopyRightSettingsStringFingerprint.kt | 16 - .../SettingsStatusLoadFingerprint.kt | 16 - .../settings/patch/TikTokSettingsPatch.kt | 98 --- .../annotations/AudioAdsCompatibility.kt | 10 - .../AudioAdsPresenterPlayFingerprint.kt | 16 - .../twitch/ad/audio/patch/AudioAdsPatch.kt | 31 - .../annotations/VideoAdsCompatibility.kt | 10 - .../fingerprints/AdsManagerFingerprint.kt | 16 - .../CheckAdEligibilityLambdaFingerprint.kt | 22 - .../ContentConfigShowAdsFingerprint.kt | 16 - .../twitch/ad/video/patch/VideoAdsPatch.kt | 60 -- .../ShowDeletedMessagesCompatibility.kt | 10 - ...etedMessageClickableSpanCtorFingerprint.kt | 19 - .../SetHasModAccessFingerprint.kt | 16 - .../patch/ShowDeletedMessagesPatch.kt | 45 -- .../annotations/DebugModeCompatibility.kt | 10 - .../IsDebugConfigEnabledFingerprint.kt | 16 - .../IsOmVerificationEnabledFingerprint.kt | 16 - .../ShouldShowDebugOptionsFingerprint.kt | 16 - .../twitch/debug/patch/DebugModePatch.kt | 49 -- .../annotations/TimelineAdsCompatibility.kt | 9 - .../TimelineTweetJsonParserFingerprint.kt | 24 - .../ad/timeline/patch/TimelineAdsPatch.kt | 77 -- .../annotations/DynamicColorCompatibility.kt | 9 - .../dynamiccolor/patch/DynamicColorPatch.kt | 87 --- .../MonochromeIconCompatibility.kt | 9 - .../monochrome/patch/MonochromeIconPatch.kt | 55 -- .../FirebaseGetCertPatchCompatibility.kt | 9 - .../GetCertMessagingFingerprint.kt | 18 - .../GetCertRegistrationFingerprint.kt | 18 - .../patch/FirebaseGetCertPatch.kt | 46 -- .../PromoCodeUnlockCompatibility.kt | 9 - .../PromoCodeUnlockFingerprint.kt | 15 - .../promocode/patch/PromoCodeUnlockPatch.kt | 47 -- .../annotation/GeneralAdsCompatibility.kt | 14 - .../bytecode/patch/GeneralBytecodeAdsPatch.kt | 0 .../ad/general/patch/GeneralAdsPatch.kt | 179 ----- .../annotations/VideoAdsCompatibility.kt | 14 - .../fingerprints/LoadVideoAdsFingerprint.kt | 18 - .../youtube/ad/video/patch/VideoAdsPatch.kt | 58 -- .../annotation/DownloadsCompatibility.kt | 14 - .../bytecode/patch/DownloadsBytecodePatch.kt | 52 -- .../resource/patch/DownloadsResourcePatch.kt | 72 -- .../annotation/SeekbarTappingCompatibility.kt | 14 - .../fingerprints/SeekbarTappingFingerprint.kt | 39 - .../SeekbarTappingParentFingerprint.kt | 49 -- .../patch/EnableSeekbarTappingPatch.kt | 110 --- .../annotation/SwipeControlsCompatibility.kt | 13 - .../SwipeControlsHostActivityFingerprint.kt | 17 - .../bytecode/SwipeControlsBytecodePatch.kt | 68 -- .../resource/SwipeControlsResourcePatch.kt | 107 --- .../annotations/AutoCaptionsCompatibility.kt | 13 - .../StartVideoInformerFingerprint.kt | 38 - .../SubtitleButtonControllerFingerprint.kt | 26 - .../fingerprints/SubtitleTrackFingerprint.kt | 24 - .../autocaptions/patch/AutoCaptionsPatch.kt | 80 --- .../AutoplayButtonCompatibility.kt | 13 - .../AutoNavInformerFingerprint.kt | 26 - .../LayoutConstructorFingerprint.kt | 16 - .../patch/HideAutoplayButtonPatch.kt | 92 --- .../PremiumHeadingCompatibility.kt | 9 - .../header/patch/PremiumHeadingPatch.kt | 51 -- .../CustomBrandingCompatibility.kt | 9 - .../icon/patch/CustomBrandingPatch.kt | 94 --- .../annotations/HideButtonsCompatibility.kt | 13 - .../layout/buttons/patch/HideButtonsPatch.kt | 81 --- .../annotations/CastPatchCompatibility.kt | 9 - .../castbutton/patch/HideCastButtonPatch.kt | 55 -- .../annotations/CommentsCompatibility.kt | 13 - .../ShortsCommentsButtonFingerprint.kt | 23 - .../comments/bytecode/patch/CommentsPatch.kt | 62 -- .../resource/patch/CommentsResourcePatch.kt | 64 -- .../FullscreenPanelsCompatibility.kt | 13 - .../FullscreenViewAdderFingerprint.kt | 17 - .../FullscreenViewAdderParentFingerprint.kt | 24 - .../patch/FullscreenPanelsRemoverPatch.kt | 65 -- .../annotations/AlbumCardsCompatibility.kt | 13 - .../fingerprints/AlbumCardsFingerprint.kt | 29 - .../bytecode/patch/AlbumCardsPatch.kt | 45 -- .../resource/patch/AlbumCardsResourcePatch.kt | 42 -- .../HideArtistCardCompatibility.kt | 13 - .../patch/HideArtistCardPatch.kt | 38 - .../patch/HideCaptionsButtonPatch.kt | 56 -- .../CrowdfundingBoxCompatibility.kt | 13 - .../CrowdfundingBoxFingerprint.kt | 29 - .../bytecode/patch/CrowdfundingBoxPatch.kt | 46 -- .../patch/CrowdfundingBoxResourcePatch.kt | 42 -- .../HideEndScreenCardsCompatibility.kt | 13 - .../fingerprints/LayoutCircleFingerprint.kt | 28 - .../fingerprints/LayoutIconFingerprint.kt | 28 - .../fingerprints/LayoutVideoFingerprint.kt | 28 - .../bytecode/patch/HideEndscreenCardsPatch.kt | 57 -- .../patch/HideEndscreenCardsResourcePatch.kt | 48 -- .../annotations/HideInfocardsCompatibility.kt | 13 - .../InfocardsIncognitoFingerprint.kt | 17 - .../InfocardsIncognitoParentFingerprint.kt | 17 - .../InfocardsMethodCallFingerprint.kt | 25 - .../hideinfocards/patch/HideInfocardsPatch.kt | 77 -- .../patch/HideInfocardsResourcePatch.kt | 40 -- .../MixPlaylistsPatchCompatibility.kt | 13 - .../CreateMixPlaylistFingerprint.kt | 30 - .../SecondCreateMixPlaylistFingerprint.kt | 30 - .../patch/MixPlaylistsPatch.kt | 64 -- .../HideTimeAndSeekbarCompatibility.kt | 13 - .../fingerprints/TimeCounterFingerprint.kt | 30 - .../patch/HideTimeAndSeekbarPatch.kt | 72 -- .../OldQualityLayoutCompatibility.kt | 13 - .../QualityMenuViewInflateFingerprint.kt | 37 - .../patch/OldQualityLayoutPatch.kt | 59 -- .../HideEmailAddressCompatibility.kt | 13 - ...ntSwitcherAccessibilityLabelFingerprint.kt | 30 - .../bytecode/patch/HideEmailAddressPatch.kt | 53 -- .../patch/HideEmailAddressResourcePatch.kt | 42 -- .../annotations/CreateButtonCompatibility.kt | 13 - .../PivotBarCreateButtonViewFingerprint.kt | 20 - .../patch/CreateButtonRemoverPatch.kt | 72 -- .../fingerprints/PivotBarFingerprint.kt | 50 -- .../annotations/ShortsButtonCompatibility.kt | 13 - .../fingerprints/PivotBarEnumFingerprint.kt | 21 - .../PivotBarShortsButtonViewFingerprint.kt | 18 - .../patch/ShortsButtonRemoverPatch.kt | 90 --- .../layout/pivotbar/utils/InjectionUtils.kt | 30 - .../PlayerPopupPanelsCompatibility.kt | 13 - .../EngagementPanelControllerFingerprint.kt | 41 -- .../patch/PlayerPopupPanelsPatch.kt | 59 -- .../annotations/HideReelsCompatibility.kt | 13 - .../fingerprints/HideReelsFingerprint.kt | 16 - .../layout/reels/patch/HideReelsPatch.kt | 51 -- .../ReturnYouTubeDislikeCompatibility.kt | 13 - .../fingerprints/DislikeFingerprint.kt | 17 - .../fingerprints/LikeFingerprint.kt | 19 - .../fingerprints/RemoveLikeFingerprint.kt | 17 - .../fingerprints/TextComponentFingerprint.kt | 14 - .../TextComponentSpecParentFingerprint.kt | 14 - .../patch/ReturnYouTubeDislikePatch.kt | 84 --- .../ReturnYouTubeDislikeResourcePatch.kt | 42 -- .../annotations/SponsorBlockCompatibility.kt | 13 - .../fingerprints/AppendTimeFingerprint.kt | 36 - .../CreateVideoPlayerSeekbarFingerprint.kt | 15 - .../NextGenWatchLayoutFingerprint.kt | 17 - .../PlayerOverlaysLayoutInitFingerprint.kt | 16 - .../RectangleFieldInvalidatorFingerprint.kt | 28 - .../ShortsPlayerConstructorFingerprint.kt | 46 -- .../patch/SponsorBlockBytecodePatch.kt | 289 -------- .../patch/SponsorBlockResourcePatch.kt | 116 --- .../StartupShortsResetCompatibility.kt | 13 - .../UserWasInShortsFingerprint.kt | 29 - .../patch/DisableShortsOnStartupPatch.kt | 59 -- .../TabletMiniPlayerCompatibility.kt | 13 - ...niPlayerDimensionsCalculatorFingerprint.kt | 28 - .../MiniPlayerOverrideFingerprint.kt | 17 - .../MiniPlayerOverrideNoContextFingerprint.kt | 17 - ...PlayerResponseModelSizeCheckFingerprint.kt | 26 - .../patch/TabletMiniPlayerPatch.kt | 105 --- .../theme/annotations/ThemeCompatibility.kt | 9 - .../fingerprints/LithoThemeFingerprint.kt | 32 - .../layout/theme/patch/LithoThemePatch.kt | 38 - .../youtube/layout/theme/patch/ThemePatch.kt | 74 -- .../annotations/WatchinVRCompatibility.kt | 13 - .../fingerprints/WatchinVRFingerprint.kt | 16 - .../layout/watchinvr/patch/WatchinVRPatch.kt | 55 -- .../annotations/HideWaterwarkCompatibility.kt | 13 - .../fingerprints/HideWatermarkFingerprint.kt | 15 - .../HideWatermarkParentFingerprint.kt | 15 - .../watermark/patch/HideWatermarkPatch.kt | 63 -- .../annotations/WideSearchbarCompatibility.kt | 13 - .../WideSearchbarOneFingerprint.kt | 18 - .../WideSearchbarOneParentFingerprint.kt | 16 - .../WideSearchbarTwoFingerprint.kt | 19 - .../WideSearchbarTwoParentFingerprint.kt | 16 - .../widesearchbar/patch/WideSearchbarPatch.kt | 120 ---- .../annotations/AutoRepeatCompatibility.kt | 13 - .../fingerprints/AutoRepeatFingerprint.kt | 18 - .../AutoRepeatParentFingerprint.kt | 20 - .../misc/autorepeat/patch/AutoRepeatPatch.kt | 88 --- .../annotations/ClientSpoofCompatibility.kt | 14 - .../UserAgentHeaderBuilderFingerprint.kt | 18 - .../clientspoof/patch/ClientSpoofPatch.kt | 37 - .../annotations/DebuggingCompatibility.kt | 9 - .../misc/debugging/patch/DebuggingPatch.kt | 60 -- .../annotations/HDRBrightnessCompatibility.kt | 13 - .../fingerprints/HDRBrightnessFingerprint.kt | 16 - .../hdrbrightness/patch/HDRBrightnessPatch.kt | 64 -- .../annotations/IntegrationsCompatibility.kt | 13 - .../fingerprints/InitFingerprint.kt | 13 - .../fingerprints/ServiceFingerprint.kt | 13 - .../StandalonePlayerFingerprint.kt | 16 - .../integrations/patch/IntegrationsPatch.kt | 59 -- .../annotation/LithoFilterCompatibility.kt | 14 - .../ComponentContextParserFingerprint.kt | 26 - .../EmptyComponentBuilderFingerprint.kt | 16 - .../litho/filter/patch/LithoFilterPatch.kt | 86 --- .../FixLocaleConfigErrorCompatibility.kt | 9 - .../patch/FixLocaleConfigErrorPatch.kt | 36 - .../patch/ResourceMappingResourcePatch.kt | 73 -- .../annotations/MicroGPatchCompatibility.kt | 13 - .../CastContextFetchFingerprint.kt | 14 - .../CastDynamiteModuleFingerprint.kt | 14 - .../CastDynamiteModuleV2Fingerprint.kt | 14 - .../GooglePlayUtilityFingerprint.kt | 18 - .../fingerprints/IntegrityCheckFingerprint.kt | 16 - .../microg/fingerprints/PrimeFingerprint.kt | 14 - .../fingerprints/ServiceCheckFingerprint.kt | 16 - .../patch/bytecode/MicroGBytecodePatch.kt | 76 -- .../patch/resource/MicroGResourcePatch.kt | 62 -- .../youtube/misc/microg/shared/Constants.kt | 9 - .../MinimizedPlaybackCompatibility.kt | 13 - .../MinimizedPlaybackKidsFingerprint.kt | 29 - .../MinimizedPlaybackManagerFingerprint.kt | 47 -- .../MinimizedPlaybackSettingsFingerprint.kt | 30 - .../patch/MinimizedPlaybackPatch.kt | 88 --- .../OpenLinksDirectlyCompatibility.kt | 13 - .../OpenLinksDirectlyFingerprintPrimary.kt | 23 - .../OpenLinksDirectlyFingerprintSecondary.kt | 28 - .../patch/OpenLinksDirectlyPatch.kt | 72 -- .../annotations/FixPlaybackCompatibility.kt | 13 - .../playback/fix/patch/FixPlaybackPatch.kt | 52 -- .../annotation/PlayerControlsCompatibility.kt | 13 - .../patch/PlayerControlsBytecodePatch.kt | 83 --- .../BottomControlsInflateFingerprint.kt | 27 - .../PlayerControlsVisibilityFingerprint.kt | 18 - .../patch/BottomControlsResourcePatch.kt | 85 --- .../PlayerOverlaysHookCompatibility.kt | 13 - ...layerOverlaysOnFinishInflateFingerprint.kt | 16 - .../patch/PlayerOverlaysHookPatch.kt | 35 - .../annotation/PlayerTypeHookCompatibility.kt | 13 - .../UpdatePlayerTypeFingerprint.kt | 40 -- .../playertype/patch/PlayerTypeHookPatch.kt | 34 - .../annotations/SettingsCompatibility.kt | 9 - .../LicenseActivityFingerprint.kt | 17 - .../fingerprints/ThemeSetterAppFingerprint.kt | 39 - .../ThemeSetterSystemFingerprint.kt | 23 - .../settings/bytecode/patch/SettingsPatch.kt | 185 ----- .../framework/components/BasePreference.kt | 14 - .../framework/components/IPreference.kt | 23 - .../components/impl/ArrayResource.kt | 9 - .../framework/components/impl/InputType.kt | 6 - .../framework/components/impl/Preference.kt | 18 - .../components/impl/PreferenceScreen.kt | 20 - .../components/impl/StringResource.kt | 10 - .../components/impl/SwitchPreference.kt | 21 - .../components/impl/TextPreference.kt | 22 - .../resource/patch/SettingsResourcePatch.kt | 302 -------- .../VideoInformationCompatibility.kt | 13 - .../CreateVideoPlayerSeekbarFingerprint.kt | 16 - ...erControllerSetTimeReferenceFingerprint.kt | 17 - .../fingerprints/PlayerInitFingerprint.kt | 17 - .../fingerprints/SeekFingerprint.kt | 15 - .../fingerprints/VideoLengthFingerprint.kt | 29 - .../fingerprints/VideoTimeFingerprint.kt | 15 - .../patch/VideoInformationPatch.kt | 178 ----- .../RememberVideoQualityCompatibility.kt | 13 - .../VideoQualityReferenceFingerprint.kt | 18 - .../VideoQualitySetterFingerprint.kt | 27 - .../VideoUserQualityChangeFingerprint.kt | 26 - .../patch/RememberVideoQualityPatch.kt | 88 --- .../CustomPlaybackSpeedCompatibility.kt | 13 - .../SpeedArrayGeneratorFingerprint.kt | 28 - .../fingerprints/SpeedLimiterFingerprint.kt | 30 - .../VideoSpeedPatchFingerprint.kt | 17 - .../custom/patch/CustomVideoSpeedPatch.kt | 195 ----- .../annotation/VideoIdCompatibility.kt | 13 - .../videoid/fingerprint/VideoIdFingerprint.kt | 23 - .../misc/video/videoid/patch/VideoIdPatch.kt | 58 -- .../CustomVideoBufferCompatibility.kt | 13 - .../fingerprints/MaxBufferFingerprint.kt | 26 - .../fingerprints/PlaybackBufferFingerprint.kt | 25 - .../fingerprints/ReBufferFingerprint.kt | 25 - .../patch/CustomVideoBufferPatch.kt | 137 ---- .../WatchWhileActivityFingerprint.kt | 17 - .../app/revanced/util/microg/Constants.kt | 130 ---- .../util/microg/MicroGBytecodeHelper.kt | 241 ------- .../util/microg/MicroGManifestHelper.kt | 58 -- .../util/microg/MicroGResourceHelper.kt | 59 -- .../revanced/util/resources/ResourceUtils.kt | 104 --- ...veproduct_youtube_background_color_108.png | Bin 3044 -> 0 bytes ...veproduct_youtube_foreground_color_108.png | Bin 5129 -> 0 bytes .../branding/mipmap-hdpi/ic_launcher.png | Bin 4571 -> 0 bytes .../mipmap-hdpi/ic_launcher_round.png | Bin 4571 -> 0 bytes ...veproduct_youtube_background_color_108.png | Bin 2937 -> 0 bytes ...veproduct_youtube_foreground_color_108.png | Bin 4366 -> 0 bytes .../branding/mipmap-mdpi/ic_launcher.png | Bin 3919 -> 0 bytes .../mipmap-mdpi/ic_launcher_round.png | Bin 3919 -> 0 bytes ...veproduct_youtube_background_color_108.png | Bin 3188 -> 0 bytes ...veproduct_youtube_foreground_color_108.png | Bin 6199 -> 0 bytes .../branding/mipmap-xhdpi/ic_launcher.png | Bin 5255 -> 0 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 5255 -> 0 bytes ...veproduct_youtube_background_color_108.png | Bin 3481 -> 0 bytes ...veproduct_youtube_foreground_color_108.png | Bin 7429 -> 0 bytes .../branding/mipmap-xxhdpi/ic_launcher.png | Bin 6719 -> 0 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 6719 -> 0 bytes ...veproduct_youtube_background_color_108.png | Bin 3893 -> 0 bytes ...veproduct_youtube_foreground_color_108.png | Bin 7945 -> 0 bytes .../branding/mipmap-xxxhdpi/ic_launcher.png | Bin 8086 -> 0 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 8086 -> 0 bytes .../drawable/revanced_yt_download_button.xml | 4 - .../youtube_controls_bottom_ui_container.xml | 4 - .../downloads/host/values/strings.xml | 4 - .../resources/microg/host/values/strings.xml | 4 - .../host/values/strings.xml | 6 - .../quantum_ic_arrow_back_white_24.png | Bin 200 -> 0 bytes .../quantum_ic_arrow_back_white_24.png | Bin 194 -> 0 bytes .../layout/revanced_settings_toolbar.xml | 4 - .../layout/revanced_settings_with_toolbar.xml | 4 - .../revanced_settings_with_toolbar_layout.xml | 5 - .../resources/settings/xml/revanced_prefs.xml | 4 - .../quantum_ic_skip_next_white_24.png | Bin 357 -> 0 bytes .../sponsorblock/drawable/ic_sb_adjust.xml | 10 - .../sponsorblock/drawable/ic_sb_compare.xml | 10 - .../sponsorblock/drawable/ic_sb_edit.xml | 10 - .../sponsorblock/drawable/ic_sb_logo.xml | 19 - .../sponsorblock/drawable/ic_sb_publish.xml | 10 - .../sponsorblock/drawable/ic_sb_voting.xml | 10 - .../host/layout/youtube_controls_layout.xml | 4 - .../sponsorblock/host/values/strings.xml | 142 ---- .../layout/inline_sponsor_overlay.xml | 5 - .../sponsorblock/layout/new_segment.xml | 107 --- .../layout/skip_sponsor_button.xml | 7 - .../drawable/ic_sc_brightness_auto.xml | 5 - .../drawable/ic_sc_brightness_manual.xml | 5 - .../drawable/ic_sc_volume_mute.xml | 5 - .../drawable/ic_sc_volume_normal.xml | 5 - .../theme/values-night-v31/styles.xml | 8 - 447 files changed, 15181 deletions(-) delete mode 100644 .gitignore delete mode 100644 .idea/.gitignore delete mode 100644 .idea/discord.xml delete mode 100644 .idea/git_toolbox_prj.xml delete mode 100644 .idea/misc.xml delete mode 100644 .idea/vcs.xml delete mode 100644 .releaserc delete mode 100644 LICENSE delete mode 100644 build.gradle.kts delete mode 100644 gradle.properties delete mode 100644 gradle/wrapper/gradle-wrapper.jar delete mode 100644 gradle/wrapper/gradle-wrapper.properties delete mode 100644 gradlew delete mode 100644 gradlew.bat delete mode 100644 patches.json delete mode 100644 settings.gradle.kts delete mode 100644 src/main/kotlin/app/revanced/extensions/Extensions.kt delete mode 100644 src/main/kotlin/app/revanced/meta/Meta.kt delete mode 100644 src/main/kotlin/app/revanced/meta/json/Generator.kt delete mode 100644 src/main/kotlin/app/revanced/meta/json/JsonPatch.kt delete mode 100644 src/main/kotlin/app/revanced/meta/readme/Extensions.kt delete mode 100644 src/main/kotlin/app/revanced/meta/readme/Generator.kt delete mode 100644 src/main/kotlin/app/revanced/meta/readme/SemanticVersion.kt delete mode 100644 src/main/kotlin/app/revanced/meta/readme/Template.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/annotations/SubscriptionUnlockCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/fingerprints/SubscriptionUnlockFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/patch/SubscriptionUnlockPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/AllCodecsReferenceFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/CodecsLockFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/AudioOnlyEnablerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/ExclusiveAudioFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/TiktokAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/ad/patch/TiktokAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/DownloadPathParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/SeekbarCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/TiktokSeekbarPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/SpeedCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/SpeedPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/AdsManagerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/ad/timeline/annotations/TimelineAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/ad/timeline/fingerprints/TimelineTweetJsonParserFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/ad/timeline/patch/TimelineAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/annotations/MonochromeIconCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/patch/MonochromeIconPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertMessagingFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertRegistrationFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ad/general/patch/GeneralAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ad/video/fingerprints/LoadVideoAdsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleButtonControllerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleTrackFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutoNavInformerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/HideAutoplayButtonPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/buttons/annotations/HideButtonsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/annotations/CastPatchCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/patch/HideCastButtonPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/comments/annotations/CommentsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/patch/CommentsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/comments/resource/patch/CommentsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/annotations/FullscreenPanelsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/patch/FullscreenPanelsRemoverPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/annotations/AlbumCardsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/patch/AlbumCardsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/resource/patch/AlbumCardsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/annotations/HideArtistCardCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/patch/HideArtistCardPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidecaptionsbutton/patch/HideCaptionsButtonPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/annotations/HideInfocardsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsMethodCallFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/patch/HideInfocardsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/resource/patch/HideInfocardsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/annotations/MixPlaylistsPatchCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/CreateMixPlaylistFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/SecondCreateMixPlaylistFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/patch/MixPlaylistsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/annotations/HideTimeAndSeekbarCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/fingerprints/TimeCounterFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/patch/HideTimeAndSeekbarPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/annotations/HideEmailAddressCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/patch/HideEmailAddressPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/annotations/CreateButtonCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/fingerprints/PivotBarCreateButtonViewFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/patch/CreateButtonRemoverPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/fingerprints/PivotBarFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/annotations/ShortsButtonCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarEnumFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarShortsButtonViewFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/patch/ShortsButtonRemoverPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/utils/InjectionUtils.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/annotations/PlayerPopupPanelsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/fingerprints/EngagementPanelControllerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/patch/PlayerPopupPanelsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/reels/fingerprints/HideReelsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ShortsPlayerConstructorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideNoContextFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerResponseModelSizeCheckFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/LithoThemePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/annotations/WatchinVRCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/fingerprints/WatchinVRFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/patch/WatchinVRPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watermark/annotations/HideWaterwarkCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/watermark/patch/HideWatermarkPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/annotations/WideSearchbarCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/patch/WideSearchbarPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatParentFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/annotations/ClientSpoofCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/patch/ClientSpoofPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/mapping/patch/ResourceMappingResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackKidsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackSettingsFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/annotations/OpenLinksDirectlyCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintPrimary.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintSecondary.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/annotations/FixPlaybackCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/patch/FixPlaybackPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/annotations/SettingsCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/BasePreference.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/IPreference.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/ArrayResource.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/InputType.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/Preference.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/PreferenceScreen.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/StringResource.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/SwitchPreference.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/TextPreference.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/MaxBufferFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/PlaybackBufferFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/ReBufferFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt delete mode 100644 src/main/kotlin/app/revanced/shared/fingerprints/WatchWhileActivityFingerprint.kt delete mode 100644 src/main/kotlin/app/revanced/util/microg/Constants.kt delete mode 100644 src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt delete mode 100644 src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt delete mode 100644 src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt delete mode 100644 src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt delete mode 100644 src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png delete mode 100644 src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png delete mode 100644 src/main/resources/branding/mipmap-hdpi/ic_launcher.png delete mode 100644 src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png delete mode 100644 src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png delete mode 100644 src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png delete mode 100644 src/main/resources/branding/mipmap-mdpi/ic_launcher.png delete mode 100644 src/main/resources/branding/mipmap-mdpi/ic_launcher_round.png delete mode 100644 src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_background_color_108.png delete mode 100644 src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png delete mode 100644 src/main/resources/branding/mipmap-xhdpi/ic_launcher.png delete mode 100644 src/main/resources/branding/mipmap-xhdpi/ic_launcher_round.png delete mode 100644 src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_background_color_108.png delete mode 100644 src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png delete mode 100644 src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png delete mode 100644 src/main/resources/branding/mipmap-xxhdpi/ic_launcher_round.png delete mode 100644 src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_background_color_108.png delete mode 100644 src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png delete mode 100644 src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png delete mode 100644 src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png delete mode 100644 src/main/resources/downloads/drawable/revanced_yt_download_button.xml delete mode 100644 src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml delete mode 100644 src/main/resources/downloads/host/values/strings.xml delete mode 100644 src/main/resources/microg/host/values/strings.xml delete mode 100644 src/main/resources/returnyoutubedislike/host/values/strings.xml delete mode 100644 src/main/resources/settings/drawable-ldrtl-xxxhdpi/quantum_ic_arrow_back_white_24.png delete mode 100644 src/main/resources/settings/drawable-xxxhdpi/quantum_ic_arrow_back_white_24.png delete mode 100644 src/main/resources/settings/layout/revanced_settings_toolbar.xml delete mode 100644 src/main/resources/settings/layout/revanced_settings_with_toolbar.xml delete mode 100644 src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml delete mode 100644 src/main/resources/settings/xml/revanced_prefs.xml delete mode 100644 src/main/resources/sponsorblock/drawable-xxxhdpi/quantum_ic_skip_next_white_24.png delete mode 100644 src/main/resources/sponsorblock/drawable/ic_sb_adjust.xml delete mode 100644 src/main/resources/sponsorblock/drawable/ic_sb_compare.xml delete mode 100644 src/main/resources/sponsorblock/drawable/ic_sb_edit.xml delete mode 100644 src/main/resources/sponsorblock/drawable/ic_sb_logo.xml delete mode 100644 src/main/resources/sponsorblock/drawable/ic_sb_publish.xml delete mode 100644 src/main/resources/sponsorblock/drawable/ic_sb_voting.xml delete mode 100644 src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml delete mode 100644 src/main/resources/sponsorblock/host/values/strings.xml delete mode 100644 src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml delete mode 100644 src/main/resources/sponsorblock/layout/new_segment.xml delete mode 100644 src/main/resources/sponsorblock/layout/skip_sponsor_button.xml delete mode 100644 src/main/resources/swipecontrols/drawable/ic_sc_brightness_auto.xml delete mode 100644 src/main/resources/swipecontrols/drawable/ic_sc_brightness_manual.xml delete mode 100644 src/main/resources/swipecontrols/drawable/ic_sc_volume_mute.xml delete mode 100644 src/main/resources/swipecontrols/drawable/ic_sc_volume_normal.xml delete mode 100644 src/main/resources/theme/values-night-v31/styles.xml diff --git a/.gitignore b/.gitignore deleted file mode 100644 index f0dfac3..0000000 --- a/.gitignore +++ /dev/null @@ -1,120 +0,0 @@ -### Java template -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar - -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -### JetBrains template -# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider -# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 - -# User-specific stuff -.idea/**/workspace.xml -.idea/**/tasks.xml -.idea/**/usage.statistics.xml -.idea/**/dictionaries -.idea/**/shelf - -# Generated files -.idea/**/contentModel.xml - -# Sensitive or high-churn files -.idea/**/dataSources/ -.idea/**/dataSources.ids -.idea/**/dataSources.local.xml -.idea/**/sqlDataSources.xml -.idea/**/dynamic.xml -.idea/**/uiDesigner.xml -.idea/**/dbnavigator.xml - -# Gradle -.idea/**/gradle.xml -.idea/**/libraries - -# Gradle and Maven with auto-import -# When using Gradle or Maven with auto-import, you should exclude module files, -# since they will be recreated, and may cause churn. Uncomment if using -# auto-import. -.idea/artifacts -.idea/compiler.xml -.idea/jarRepositories.xml -.idea/modules.xml -.idea/*.iml -.idea/modules -*.iml -*.ipr - -# CMake -cmake-build-*/ - -# Mongo Explorer plugin -.idea/**/mongoSettings.xml - -# File-based project format -*.iws - -# IntelliJ -out/ - -# mpeltonen/sbt-idea plugin -.idea_modules/ - -# JIRA plugin -atlassian-ide-plugin.xml - -# Cursive Clojure plugin -.idea/replstate.xml - -# Crashlytics plugin (for Android Studio and IntelliJ) -com_crashlytics_export_strings.xml -crashlytics.properties -crashlytics-build.properties -fabric.properties - -# Editor-based Rest Client -.idea/httpRequests - -# Android studio 3.1+ serialized cache file -.idea/caches/build_file_checksums.ser - -### Gradle template -.gradle -**/build/ -!src/**/build/ - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Cache of project -.gradletasknamecache - -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties - -# Potentially copyrighted test APK -*.apk - -# Ignore vscode config -.vscode/ diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 877c6d9..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,9 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ -/kotlinc.xml diff --git a/.idea/discord.xml b/.idea/discord.xml deleted file mode 100644 index d8e9561..0000000 --- a/.idea/discord.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/git_toolbox_prj.xml b/.idea/git_toolbox_prj.xml deleted file mode 100644 index 02b915b..0000000 --- a/.idea/git_toolbox_prj.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index f1854e4..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 7ddfc9e..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.releaserc b/.releaserc deleted file mode 100644 index 1d2937b..0000000 --- a/.releaserc +++ /dev/null @@ -1,43 +0,0 @@ -{ - "branches": [ - "main", - { - "name": "dev", - "prerelease": true - } - ], - "plugins": [ - ["@semantic-release/commit-analyzer", { - "releaseRules": [ - {"type": "build", "release": "patch"} - ] - }], - "@semantic-release/release-notes-generator", - "@semantic-release/changelog", - "gradle-semantic-release-plugin", - [ - "@semantic-release/git", - { - "assets": [ - "README.md", - "CHANGELOG.md", - "gradle.properties", - "patches.json" - ] - } - ], - [ - "@semantic-release/github", - { - "assets": [ - { - "path": "build/libs/*.jar" - }, - { - "path": "patches.json" - } - ] - } - ] - ] -} diff --git a/LICENSE b/LICENSE deleted file mode 100644 index f288702..0000000 --- a/LICENSE +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 07265f8..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,66 +0,0 @@ -plugins { - kotlin("jvm") version "1.7.0" -} - -group = "app.revanced" - -val githubUsername: String = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR") -val githubPassword: String = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN") - -repositories { - mavenCentral() - mavenLocal() - maven { - url = uri("https://maven.pkg.github.com/revanced/revanced-patcher") - credentials { - username = githubUsername - password = githubPassword - } - } -} - -dependencies { - implementation("app.revanced:revanced-patcher:6.0.2") - implementation("app.revanced:multidexlib2:2.5.2.r2") - // Required for meta - implementation("com.google.code.gson:gson:2.9.1") -} - -tasks { - register("generateBundle") { - description = "Generate dex files from build and bundle them in the jar file" - dependsOn(build) - - doLast { - val androidHome = System.getenv("ANDROID_HOME") ?: throw GradleException("ANDROID_HOME not found") - val d8 = "${androidHome}/build-tools/32.0.0/d8" - val input = configurations.archives.get().allArtifacts.files.files.first().absolutePath - val work = File("${buildDir}/libs") - - exec { - workingDir = work - commandLine = listOf(d8, input) - } - - exec { - workingDir = work - commandLine = listOf("zip", "-u", input, "classes.dex") - } - } - } - register("generateMeta") { - description = "Generate metadata for this bundle" - dependsOn(build) - - classpath = sourceSets["main"].runtimeClasspath - mainClass.set("app.revanced.meta.Meta") - } - // Dummy task to fix the Gradle semantic-release plugin. - // Remove this if you forked it to support building only. - // Tracking issue: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435 - register("publish") { - group = "publish" - description = "Dummy task" - dependsOn(named("generateBundle"), named("generateMeta")) - } -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 7874ced..0000000 --- a/gradle.properties +++ /dev/null @@ -1,2 +0,0 @@ -kotlin.code.style = official -version = 2.111.2 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7454180f2ae8848c63b8b4dea2cb829da983f2fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 59536 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�cCgb#m`a|c{XyiMM^|2OP(X?bxKl6T=|ov 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 JgTXZr4*< \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MSYS* | MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/patches.json b/patches.json deleted file mode 100644 index c1de998..0000000 --- a/patches.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"ginlemon.iconpackstudio","versions":[]}]},{"name":"tiktok-ads","description":"Removes ads from TikTok.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"tiktok-speed","description":"Enables the playback speed option for all videos.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"tiktok-download","description":"Removes download restrictions and changes the default path to download to.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["tiktok-integrations","tiktok-settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"tiktok-seekbar","description":"Show progress bar for all video.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"tiktok-settings","description":"Add settings menu to TikTok.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["tiktok-integrations"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"tiktok-force-login","description":"Do not force login.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"tiktok-feed-filter","description":"Filters tiktok videos: removing ads, removing livestreams.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["tiktok-integrations","tiktok-settings"],"compatiblePackages":[{"name":"com.ss.android.ugc.trill","versions":[]},{"name":"com.zhiliaoapp.musically","versions":[]}]},{"name":"timeline-ads","description":"Removes ads from the Twitter timeline.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"dynamic-color","description":"Replaces the default Twitter Blue with the users Material You palette.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"monochrome-icon","description":"Adds a monochrome icon.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.twitter.android","versions":[]}]},{"name":"promo-code-unlock","description":"Disables the validation of promo code. Any code will work to unlock all features.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["spoof-cert-patch"],"compatiblePackages":[{"name":"de.dwd.warnapp","versions":[]}]},{"name":"disable-ads","description":"Disables ads in HexEditor.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.myprog.hexedit","versions":[]}]},{"name":"spotify-theme","description":"Applies a custom theme.","version":"0.0.1","excluded":false,"deprecated":false,"options":[{"key":"backgroundColor","title":"Background color","description":"The background color. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentColor","title":"Accent color","description":"The accent color (\u0027spotify green\u0027 by default). Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"accentPressedColor","title":"Pressed accent for the dark theme","description":"The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":["locale-config-fix"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"disable-capture-restriction","description":"Allows capturing Spotify\u0027s audio output while screen sharing or screen recording.","version":"0.0.2","excluded":false,"deprecated":false,"options":[],"dependencies":["disable-capture-restriction-resource-patch"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"hide-premium-navbar","description":"Removes the premium tab from the navbar.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["resource-mapping"],"compatiblePackages":[{"name":"com.spotify.music","versions":[]}]},{"name":"hide-crowdfunding-box","description":"Hides the crowdfunding box between the player and video description.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","crowdfunding-box-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-time-and-seekbar","description":"Hides progress bar and time counter on videos.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-video-buttons","description":"Adds options to hide action buttons under a video.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"enable-wide-searchbar","description":"Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-captions-button","description":"Hides the captions button on video player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-shorts-button","description":"Hides the shorts button on the navigation bar.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-create-button","description":"Hides the create button in the navigation bar.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","resource-mapping","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"disable-startup-shorts-player","description":"Disables playing YouTube Shorts when launching YouTube.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-endscreen-cards","description":"Hides the suggested video cards at the end of a video in fullscreen.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","hide-endscreen-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-cast-button","description":"Hides the cast button in the video player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"sponsorblock","description":"Integrate SponsorBlock.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["video-information","player-controls-bytecode-patch","integrations","sponsorblock-resource-patch","video-id-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-autoplay-button","description":"Hides the autoplay button in the video player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings","resource-mapping"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-watch-in-vr","description":"Hides the Watch in VR option from the player settings flyout panel.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-album-cards","description":"Hides the album cards below the artist description.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","hide-album-cards-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"disable-auto-player-popup-panels","description":"Disable automatic popup panels (playlist or live chat) on video player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"disable-auto-captions","description":"Disable forced captions from being automatically enabled.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"disable-fullscreen-panels","description":"Disables video description and comments panel in fullscreen view.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-artist-card","description":"Hides the artist card below the searchbar.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["resource-mapping","LithoFilterPatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"return-youtube-dislike","description":"Shows the dislike count of videos using the Return YouTube Dislike API.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","video-id-hook","return-youtube-dislike-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"comments","description":"Hides components related to comments.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","comments-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"theme","description":"Applies a custom theme.","version":"0.0.1","excluded":false,"deprecated":false,"options":[{"key":"darkThemeBackgroundColor","title":"Background color for the dark theme","description":"The background color of the dark theme. Can be a hex color or a resource reference.","required":false,"choices":null},{"key":"lightThemeBackgroundColor","title":"Background color for the light theme","description":"The background color of the light theme. Can be a hex color or a resource reference.","required":false,"choices":null}],"dependencies":["litho-components-theme","locale-config-fix"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"hide-email-address","description":"Hides the email address in the account switcher.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","hide-email-address-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"tablet-mini-player","description":"Enables the tablet mini player layout.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-watermark","description":"Hides creator\u0027s watermarks on videos.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-info-cards","description":"Hides info-cards in videos.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","HideInfocardsResourcePatch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hide-my-mix","description":"Hides mix playlists.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.36.39","17.37.35","17.38.36","17.39.35","17.40.41","17.41.37","17.42.35","17.43.36"]}]},{"name":"custom-branding","description":"Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).","version":"0.0.1","excluded":false,"deprecated":false,"options":[{"key":"appName","title":"Application Name","description":"The name of the application it will show on your home screen.","required":true,"choices":null},{"key":"iconPath","title":"App Icon Path","description":"A path containing mipmap resource folders with icons.","required":false,"choices":null}],"dependencies":["locale-config-fix"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"premium-heading","description":"Shows premium branding on the home screen.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["locale-config-fix"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"old-quality-layout","description":"Enables the original quality flyout menu.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"general-ads","description":"Removes general ads.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["locale-config-fix","LithoFilterPatch","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"video-ads","description":"Removes ads in the video player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings","fix-playback"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"swipe-controls","description":"Adds volume and brightness swipe controls.","version":"0.0.3","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","player-type-hook","swipe-controls-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"downloads","description":"Enables downloading music and videos from YouTube.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["downloads-resource-patch","player-controls-bytecode-patch","video-id-hook"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"seekbar-tapping","description":"Enables tap-to-seek on the seekbar of the video player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"settings","description":"Adds settings for ReVanced to YouTube.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings-resource-patch"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"open-links-directly","description":"Bypasses redirect links and allows opening links directly.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.34.36","17.36.39","17.38.36","17.39.35","17.40.41","17.42.35","17.43.36"]}]},{"name":"microg-support","description":"Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["microg-resource-patch","hide-cast-button","client-spoof"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"custom-video-buffer","description":"Lets you change the buffers of videos.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"debugging","description":"Adds debugging options.","version":"0.0.1","excluded":false,"deprecated":false,"options":[{"key":"debuggable","title":"App debugging","description":"Whether to make the app debuggable on Android.","required":false,"choices":null}],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]}]},{"name":"client-spoof","description":"Spoofs the YouTube or Vanced client to prevent playback issues.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.youtube","versions":[]},{"name":"com.vanced.android.youtube","versions":[]}]},{"name":"always-autorepeat","description":"Always repeats the playing video again.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"minimized-playback","description":"Enables minimized and background playback.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"custom-video-speed","description":"Adds more video speed options.","version":"0.0.1","excluded":false,"deprecated":false,"options":[{"key":"granularity","title":"Video speed granularity","description":"The granularity of the video speeds. The higher the value, the more speeds will be available.","required":true,"choices":null},{"key":"min","title":"Minimum video speed","description":"The minimum video speed.","required":true,"choices":null},{"key":"max","title":"Maximum video speed","description":"The maximum video speed. Must be greater than the minimum video speed and smaller than 5.","required":true,"choices":null}],"dependencies":["integrations"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"remember-video-quality","description":"Adds the ability to remember the video quality you chose in the video quality flyout.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","video-id-hook","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"hdr-auto-brightness","description":"Makes the brightness of HDR videos follow the system default.","version":"0.0.2","excluded":false,"deprecated":false,"options":[],"dependencies":["integrations","settings"],"compatiblePackages":[{"name":"com.google.android.youtube","versions":["17.36.37","17.41.37","17.42.35","17.43.36"]}]},{"name":"unlock-themes","description":"Unlocks all themes.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.ticktick.task","versions":[]}]},{"name":"debug-mode","description":"Enables Twitch\u0027s internal debugging mode.","version":"0.0.1","excluded":true,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"block-audio-ads","description":"Blocks audio ads in streams and VODs.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"block-video-ads","description":"Blocks video ads in streams and VODs.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"show-deleted-messages","description":"Shows deleted chat messages behind a clickable spoiler.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"tv.twitch.android.app","versions":[]}]},{"name":"pflotsh-ecmwf-subscription-unlock","description":"Unlocks all subscription features.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.garzotto.pflotsh.ecmwf_a","versions":["3.5.4"]}]},{"name":"tasteBuilder-remover","description":"Removes the \"Tell us which artists you like\" card from the home screen.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"hide-get-premium","description":"Removes all \"Get Premium\" evidences from the avatar menu.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"minimized-playback-music","description":"Enables minimized playback on Kids music.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"compact-header","description":"Hides the music category bar at the top of the homepage.","version":"0.0.1","excluded":true,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"upgrade-button-remover","description":"Removes the upgrade tab from the pivot bar.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"music-video-ads","description":"Removes ads in the music player.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"background-play","description":"Enables playing music in the background.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"exclusive-audio-playback","description":"Enables the option to play music without video.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"codecs-unlock","description":"Adds more audio codec options. The new audio codecs usually result in better audio quality.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"music-microg-support","description":"Allows YouTube Music ReVanced to run without root and under a different package name.","version":"0.0.2","excluded":false,"deprecated":false,"options":[],"dependencies":["music-microg-resource-patch"],"compatiblePackages":[{"name":"com.google.android.apps.youtube.music","versions":["5.14.53","5.16.51","5.17.51","5.21.52","5.22.54","5.23.50","5.25.51","5.25.52","5.26.52","5.27.51","5.28.52","5.29.52","5.31.50"]}]},{"name":"premium-icon-reddit","description":"Unlocks premium Reddit app icons.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"general-reddit-ads","description":"Removes general ads from the Reddit frontpage and subreddits.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.reddit.frontpage","versions":[]}]},{"name":"unlock-pro","description":"Unlocks all pro features.","version":"0.0.1","excluded":false,"deprecated":false,"options":[],"dependencies":[],"compatiblePackages":[{"name":"com.awedea.nyx","versions":[]}]}] \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 472c476..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "revanced-patches" diff --git a/src/main/kotlin/app/revanced/extensions/Extensions.kt b/src/main/kotlin/app/revanced/extensions/Extensions.kt deleted file mode 100644 index 6833bde..0000000 --- a/src/main/kotlin/app/revanced/extensions/Extensions.kt +++ /dev/null @@ -1,201 +0,0 @@ -package app.revanced.extensions - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patcher.util.smali.toInstruction -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.MutableMethodImplementation -import org.jf.dexlib2.builder.instruction.BuilderInstruction11n -import org.jf.dexlib2.builder.instruction.BuilderInstruction11x -import org.jf.dexlib2.builder.instruction.BuilderInstruction21t -import org.jf.dexlib2.builder.instruction.BuilderInstruction35c -import org.jf.dexlib2.immutable.reference.ImmutableMethodReference -import org.w3c.dom.Node -import java.nio.file.Files - -/** - * traverse the class hierarchy starting from the given root class - * - * @param targetClass the class to start traversing the class hierarchy from - * @param callback function that is called for every class in the hierarchy - */ -fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) { - callback(targetClass) - this.findClass(targetClass.superclass ?: return)?.mutableClass?.let { - traverseClassHierarchy(it, callback) - } -} - -/** - * apply a transform to all methods of the class - * - * @param transform the transformation function. original method goes in, transformed method goes out - */ -fun MutableClass.transformMethods(transform: MutableMethod.() -> MutableMethod) { - val transformedMethods = methods.map { it.transform() } - methods.clear() - methods.addAll(transformedMethods) -} - -/** - * Insert an event hook at the top of the method. If the hook returns true, the event is consumed and the method will return with true - * - * the hook method MUST return a boolean and MUST take two parameters, like so: - * fun hook(thisRef: Object, eventData: Object): Boolean {} - * - * The final injected code will resemble the following logic: - * if( YouHook(this, event) ) { return true; } - * ... - * - * @param hookRef reference to the hook method - */ -internal fun MutableMethod.injectConsumableEventHook(hookRef: ImmutableMethodReference) { - val isStaticMethod = AccessFlags.STATIC.isSet(this.accessFlags) - this.implementation?.let { impl -> - // create label to index 0 to continue to the normal program flow - val lblContinueNormalFlow = impl.newLabelForIndex(0) - - // define registers - /** V0 */ - val regV0 = 0 - - /** this */ - val regP0 = impl.registerCount - this.parameters.size - (if (isStaticMethod) 0 else 1) - - /** motionEvent */ - val regP1 = regP0 + 1 - - // insert instructions at the start of the method: - // if( Hook(this, event) ) { return true; } - impl.addInstructions( - 0, listOf( - // invoke-static { p0, p1 } - BuilderInstruction35c( - Opcode.INVOKE_STATIC, - 2, - regP0, - regP1, - 0, 0, 0, - hookRef - ), - - // move-result v0 - BuilderInstruction11x( - Opcode.MOVE_RESULT, - regV0 - ), - - // if-eqz v0, :continue_normal_flow - BuilderInstruction21t( - Opcode.IF_EQZ, - regV0, - lblContinueNormalFlow - ), - - // const/4 v0, 0x1 - BuilderInstruction11n( - Opcode.CONST_4, - regV0, - 0x1 - ), - - // return v0 - BuilderInstruction11x( - Opcode.RETURN, - regV0 - ) - - // :continue_normal_flow - ) - ) - } -} - -/** - * inject resources into the patched app - * - * @param classLoader classloader to use for loading the resources - * @param patchDirectoryPath path to the files. this will be the directory you created under the 'resources' source folder - * @param resourceType the resource type, for example 'drawable'. this has to match both the source and the target - * @param resourceFileNames names of all resources of this type to inject - */ -fun ResourceContext.injectResources( - classLoader: ClassLoader, - patchDirectoryPath: String, - resourceType: String, - resourceFileNames: List -) { - resourceFileNames.forEach { name -> - val relativePath = "$resourceType/$name" - val sourceRes = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath") - ?: throw PatchResultError("could not open resource '$patchDirectoryPath/$relativePath'") - - Files.copy( - sourceRes, - this["res"].resolve(relativePath).toPath() - ) - } -} - -/** - * inject strings into the patched app - * - * @param classLoader classloader to use for loading the resources - * @param patchDirectoryPath path to the files. this will be the directory you created under the 'resources' source folder - * @param languageIdentifier ISO 639-2 two- letter language code identifier (aka the one android uses for values directory) - */ -fun ResourceContext.injectStrings( - classLoader: ClassLoader, - patchDirectoryPath: String, - languageIdentifier: String? = null, -) { - val relativePath = - if (languageIdentifier.isNullOrBlank()) "values/strings.xml" else "values/strings-$languageIdentifier.xml" - - // open source strings.xml - val sourceInputStream = classLoader.getResourceAsStream("$patchDirectoryPath/$relativePath") - ?: throw PatchResultError("failed to open '$patchDirectoryPath/$relativePath'") - xmlEditor[sourceInputStream].use { sourceStringsXml -> - val strings = sourceStringsXml.file.getElementsByTagName("resources").item(0).childNodes - - // open target strings.xml - xmlEditor["res/$relativePath"].use { targetStringsXml -> - val targetFile = targetStringsXml.file - val targetRootNode = targetFile.getElementsByTagName("resources").item(0) - - // process all children strings in the source - for (i in 0 until strings.length) { - // clone the node from source to target - val node = strings.item(i).cloneNode(true) - targetFile.adoptNode(node) - targetRootNode.appendChild(node) - } - } - } -} - -internal fun Node.doRecursively(action: (Node) -> Unit) { - action(this) - for (i in 0 until this.childNodes.length) this.childNodes.item(i).doRecursively(action) -} - -internal fun String.startsWithAny(vararg prefixes: String): Boolean { - for (prefix in prefixes) - if (this.startsWith(prefix)) - return true - - return false -} - -internal fun String.equalsAny(vararg other: String): Boolean { - for (_other in other) - if (this == _other) - return true - - return false -} diff --git a/src/main/kotlin/app/revanced/meta/Meta.kt b/src/main/kotlin/app/revanced/meta/Meta.kt deleted file mode 100644 index 6be5ed0..0000000 --- a/src/main/kotlin/app/revanced/meta/Meta.kt +++ /dev/null @@ -1,27 +0,0 @@ -package app.revanced.meta - -import app.revanced.meta.json.generateJson -import app.revanced.meta.readme.generateText -import app.revanced.patcher.data.Context -import app.revanced.patcher.patch.Patch -import app.revanced.patcher.util.patch.PatchBundle -import java.io.File - -typealias Bundle = List>> - -object Meta { - @JvmStatic - fun main(args: Array) { - val patches = accumulatePatches() - if (patches.isEmpty()) throw IllegalStateException("No patches found") - - generateText(patches) - generateJson(patches) - } -} - -fun accumulatePatches() = PatchBundle.Jar( - File("build/libs/").listFiles()!!.first { - it.name.startsWith("revanced-patches-") && it.name.endsWith(".jar") - }.absolutePath -).loadPatches() \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/meta/json/Generator.kt b/src/main/kotlin/app/revanced/meta/json/Generator.kt deleted file mode 100644 index b7a87a4..0000000 --- a/src/main/kotlin/app/revanced/meta/json/Generator.kt +++ /dev/null @@ -1,50 +0,0 @@ -package app.revanced.meta.json - -import app.revanced.meta.Bundle -import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages -import app.revanced.patcher.extensions.PatchExtensions.dependencies -import app.revanced.patcher.extensions.PatchExtensions.deprecated -import app.revanced.patcher.extensions.PatchExtensions.description -import app.revanced.patcher.extensions.PatchExtensions.include -import app.revanced.patcher.extensions.PatchExtensions.options -import app.revanced.patcher.extensions.PatchExtensions.patchName -import app.revanced.patcher.extensions.PatchExtensions.version -import app.revanced.patcher.patch.PatchOption -import com.google.gson.GsonBuilder -import java.io.File - -private val gson = GsonBuilder().serializeNulls().create() - -fun generateJson(bundle: Bundle) { - val patches = bundle.map { - JsonPatch( - it.patchName, - it.description ?: "This patch has no description.", - it.version ?: "0.0.0", - !it.include, - it.deprecated != null, - it.options?.map { option -> - Option( - option.key, - option.title, - option.description, - option.required, - option.let { lo -> - if (lo is PatchOption.ListOption<*>) { - lo.options.toMutableList().toTypedArray() - } else null - } - ) - }?.toTypedArray() ?: emptyArray(), - it.dependencies?.map { dep -> - dep.java.patchName - }?.toTypedArray() ?: emptyArray(), - it.compatiblePackages?.map { pkg -> - CompatiblePackage(pkg.name, pkg.versions) - }?.toTypedArray() ?: emptyArray() - ) - } - - val json = File("patches.json") - json.writeText(gson.toJson(patches)) -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/meta/json/JsonPatch.kt b/src/main/kotlin/app/revanced/meta/json/JsonPatch.kt deleted file mode 100644 index 9099fc3..0000000 --- a/src/main/kotlin/app/revanced/meta/json/JsonPatch.kt +++ /dev/null @@ -1,27 +0,0 @@ -@file:Suppress("ArrayInDataClass") // We don't need it here. - -package app.revanced.meta.json - -data class JsonPatch( - val name: String, - val description: String, - val version: String, - val excluded: Boolean, - val deprecated: Boolean, - val options: Array

\n") - - output.appendLine(TABLE_HEADER) - pkg.value.forEach { output.appendLine("| `${it.patchName}` | ${it.description} | ${it.getLatestVersion() ?: "all"} |") } - - output.appendLine("
\n") - } - - val readmeTemplate = Template(File("README-template.md").readText()) - readmeTemplate.replaceVariable(TABLE_REGEX, output.toString()) - - val readme = File("README.md") - readme.writeText(readmeTemplate.toString()) -} diff --git a/src/main/kotlin/app/revanced/meta/readme/SemanticVersion.kt b/src/main/kotlin/app/revanced/meta/readme/SemanticVersion.kt deleted file mode 100644 index 6c461f2..0000000 --- a/src/main/kotlin/app/revanced/meta/readme/SemanticVersion.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.meta.readme - -data class SemanticVersion(val major: Int, val minor: Int, val patch: Int) { - companion object { - fun fromString(version: String): SemanticVersion { - val parts = version.split(".") - if (parts.count() != 3) throw IllegalArgumentException("Invalid semantic version") - val versionNumbers = parts.map { it.toInt() } - return SemanticVersion(versionNumbers[0], versionNumbers[1], versionNumbers[2]) - } - } - - override fun toString(): String = "$major.$minor.$patch" -} - -object SemanticVersionComparator : Comparator { - override fun compare(a: SemanticVersion, b: SemanticVersion): Int = when { - a.major != b.major -> a.major - b.major - a.minor != b.minor -> a.minor - b.minor - else -> a.patch - b.patch - } -} diff --git a/src/main/kotlin/app/revanced/meta/readme/Template.kt b/src/main/kotlin/app/revanced/meta/readme/Template.kt deleted file mode 100644 index 3b952c9..0000000 --- a/src/main/kotlin/app/revanced/meta/readme/Template.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.meta.readme - -class Template(template: String) { - val result = StringBuilder(template) - - fun replaceVariable(regex: Regex, value: String) { - val range = regex.find(result)!!.range - result.replace(range.first, range.last + 1, value) - } - - override fun toString(): String = result.toString() -} diff --git a/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/annotations/SubscriptionUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/annotations/SubscriptionUnlockCompatibility.kt deleted file mode 100644 index ce13e94..0000000 --- a/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/annotations/SubscriptionUnlockCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.ecmwf.misc.subscription.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.garzotto.pflotsh.ecmwf_a", arrayOf("3.5.4") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SubscriptionUnlockCompatibility diff --git a/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/fingerprints/SubscriptionUnlockFingerprint.kt b/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/fingerprints/SubscriptionUnlockFingerprint.kt deleted file mode 100644 index 46feaaf..0000000 --- a/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/fingerprints/SubscriptionUnlockFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.ecmwf.misc.subscription.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.ecmwf.misc.subscription.annotations.SubscriptionUnlockCompatibility - -@Name("subscription-unlock") -@SubscriptionUnlockCompatibility -@Version("0.0.1") -object SubscriptionUnlockFingerprint : MethodFingerprint( - "Z", - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("MapsActivity;") && methodDef.name == "t0" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/patch/SubscriptionUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/patch/SubscriptionUnlockPatch.kt deleted file mode 100644 index 2c1bf92..0000000 --- a/src/main/kotlin/app/revanced/patches/ecmwf/misc/subscription/patch/SubscriptionUnlockPatch.kt +++ /dev/null @@ -1,47 +0,0 @@ -package app.revanced.patches.ecmwf.misc.subscription.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.ecmwf.misc.subscription.annotations.SubscriptionUnlockCompatibility -import app.revanced.patches.ecmwf.misc.subscription.fingerprints.SubscriptionUnlockFingerprint - -@Patch -@Name("pflotsh-ecmwf-subscription-unlock") -@Description("Unlocks all subscription features.") -@SubscriptionUnlockCompatibility -@Version("0.0.1") -class SubscriptionUnlockPatch : BytecodePatch( - listOf( - SubscriptionUnlockFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val result = SubscriptionUnlockFingerprint.result!! - val method = result.mutableMethod - - val index = method.implementation!!.instructions.size - - // remove R() at 10212 - method.removeInstruction(index - 3) - // remove R() at 10206 - method.removeInstruction(index - 5) - - val insertIndex = index - - method.addInstructions( - insertIndex - 1 - 2, - """ - const/4 p1, 0x1 - """ - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt deleted file mode 100644 index e0ae0e0..0000000 --- a/src/main/kotlin/app/revanced/patches/hexeditor/ad/annotations/HexEditorAdsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.hexeditor.ad.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.myprog.hexedit") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HexEditorAdsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt deleted file mode 100644 index a01991a..0000000 --- a/src/main/kotlin/app/revanced/patches/hexeditor/ad/fingerprints/PrimaryAdsFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.hexeditor.ad.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.hexeditor.ad.annotations.HexEditorAdsCompatibility - -@Name("ads-fingerprint-primary") -@HexEditorAdsCompatibility -@Version("0.0.1") -object PrimaryAdsFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("PreferencesHelper;") && methodDef.name == "isAdsDisabled" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt b/src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt deleted file mode 100644 index 67bc094..0000000 --- a/src/main/kotlin/app/revanced/patches/hexeditor/ad/patch/HexEditorAdsPatch.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.revanced.patches.hexeditor.ad.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.extensions.replaceInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.hexeditor.ad.annotations.HexEditorAdsCompatibility -import app.revanced.patches.hexeditor.ad.fingerprints.PrimaryAdsFingerprint - -@Patch -@Name("disable-ads") -@Description("Disables ads in HexEditor.") -@HexEditorAdsCompatibility -@Version("0.0.1") -class HexEditorAdsPatch : BytecodePatch( - listOf( - PrimaryAdsFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = PrimaryAdsFingerprint.result!!.mutableMethod - - method.replaceInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt deleted file mode 100644 index 649e066..0000000 --- a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/annotations/UnlockProCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.iconpackstudio.misc.pro.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("ginlemon.iconpackstudio")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class UnlockProCompatibility diff --git a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt deleted file mode 100644 index 5937d38..0000000 --- a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/fingerprints/CheckProFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.iconpackstudio.misc.pro.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.iconpackstudio.misc.pro.annotations.UnlockProCompatibility - -@Name("check-pro-fingerprint") -@UnlockProCompatibility -@Version("0.0.1") -object CheckProFingerprint : MethodFingerprint( - "Z", - customFingerprint = { it.definingClass.endsWith("IPSPurchaseRepository;")} -) diff --git a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt deleted file mode 100644 index a4a2d4f..0000000 --- a/src/main/kotlin/app/revanced/patches/iconpackstudio/misc/pro/patch/UnlockProPatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.iconpackstudio.misc.pro.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.iconpackstudio.misc.pro.annotations.UnlockProCompatibility -import app.revanced.patches.iconpackstudio.misc.pro.fingerprints.CheckProFingerprint - -@Patch -@Name("unlock-pro") -@Description("Unlocks all pro features.") -@UnlockProCompatibility -@Version("0.0.1") -class UnlockProPatch : BytecodePatch( - listOf( - CheckProFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = CheckProFingerprint.result!!.mutableMethod - method.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt deleted file mode 100644 index d7c0db3..0000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/annotations/MusicVideoAdsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.ad.video.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MusicVideoAdsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt deleted file mode 100644 index 218deb0..0000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsConstructorFingerprint.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.patches.music.ad.video.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("show-video-ads-constructor-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@MusicVideoAdsCompatibility -@Version("0.0.1") -object ShowMusicVideoAdsConstructorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4, - Opcode.IPUT_BOOLEAN, - Opcode.RETURN_VOID - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt deleted file mode 100644 index 4ef5413..0000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/fingerprints/ShowMusicVideoAdsFingerprint.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.music.ad.video.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("show-video-ads-method-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@MusicVideoAdsCompatibility -@Version("0.0.1") -object ShowMusicVideoAdsFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), listOf( - Opcode.IPUT_BOOLEAN, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt deleted file mode 100644 index bbf4848..0000000 --- a/src/main/kotlin/app/revanced/patches/music/ad/video/patch/MusicVideoAdsPatch.kt +++ /dev/null @@ -1,40 +0,0 @@ -package app.revanced.patches.music.ad.video.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.ad.video.annotations.MusicVideoAdsCompatibility -import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsConstructorFingerprint -import app.revanced.patches.music.ad.video.fingerprints.ShowMusicVideoAdsFingerprint - -@Patch -@Name("music-video-ads") -@Description("Removes ads in the music player.") -@MusicVideoAdsCompatibility -@Version("0.0.1") -class MusicVideoAdsPatch : BytecodePatch( - listOf( - ShowMusicVideoAdsConstructorFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - ShowMusicVideoAdsFingerprint.resolve(context, ShowMusicVideoAdsConstructorFingerprint.result!!.classDef) - - val result = ShowMusicVideoAdsFingerprint.result!! - - result.mutableMethod.addInstructions( - result.scanResult.patternScanResult!!.startIndex, """ - const/4 p1, 0x0 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt deleted file mode 100644 index f7305e2..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/annotations/CodecsUnlockCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.audio.codecs.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CodecsUnlockCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/AllCodecsReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/AllCodecsReferenceFingerprint.kt deleted file mode 100644 index abf7d8f..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/AllCodecsReferenceFingerprint.kt +++ /dev/null @@ -1,57 +0,0 @@ -package app.revanced.patches.music.audio.codecs.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("all-codecs-reference-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@CodecsUnlockCompatibility -@Version("0.0.1") -object AllCodecsReferenceFingerprint : MethodFingerprint( - "J", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_BOOLEAN, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.IPUT_BOOLEAN, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.GOTO, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.IGET_BOOLEAN, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.IPUT_BOOLEAN, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.GOTO, - Opcode.MOVE_EXCEPTION, - Opcode.INVOKE_SUPER, - Opcode.MOVE_RESULT_WIDE, - Opcode.RETURN_WIDE - ), listOf("itag") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/CodecsLockFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/CodecsLockFingerprint.kt deleted file mode 100644 index dea41a2..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/fingerprints/CodecsLockFingerprint.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.patches.music.audio.codecs.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("codec-lock-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@CodecsUnlockCompatibility -@Version("0.0.1") -object CodecsLockFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, opcodes = listOf( - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.INVOKE_DIRECT, - Opcode.RETURN_OBJECT - ), - strings = listOf("eac3_supported") -) diff --git a/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt deleted file mode 100644 index 9ff6916..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/codecs/patch/CodecsUnlockPatch.kt +++ /dev/null @@ -1,56 +0,0 @@ -package app.revanced.patches.music.audio.codecs.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.toInstruction -import app.revanced.patches.music.audio.codecs.annotations.CodecsUnlockCompatibility -import app.revanced.patches.music.audio.codecs.fingerprints.AllCodecsReferenceFingerprint -import app.revanced.patches.music.audio.codecs.fingerprints.CodecsLockFingerprint -import org.jf.dexlib2.Opcode - -@Patch -@Name("codecs-unlock") -@Description("Adds more audio codec options. The new audio codecs usually result in better audio quality.") -@CodecsUnlockCompatibility -@Version("0.0.1") -class CodecsUnlockPatch : BytecodePatch( - listOf( - CodecsLockFingerprint, AllCodecsReferenceFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val codecsLockResult = CodecsLockFingerprint.result!! - - val implementation = codecsLockResult.mutableMethod.implementation!! - - val scanResultStartIndex = codecsLockResult.scanResult.patternScanResult!!.startIndex - val instructionIndex = scanResultStartIndex + - if (implementation.instructions[scanResultStartIndex - 1].opcode == Opcode.CHECK_CAST) { - // for 5.16.xx and lower - -3 - } else { - // since 5.17.xx - -2 - } - - val allCodecsResult = AllCodecsReferenceFingerprint.result!! - val allCodecsMethod = - context.toMethodWalker(allCodecsResult.method) - .nextMethod(allCodecsResult.scanResult.patternScanResult!!.startIndex) - .getMethod() - - implementation.replaceInstruction( - instructionIndex, - "invoke-static {}, ${allCodecsMethod.definingClass}->${allCodecsMethod.name}()Ljava/util/Set;".toInstruction() - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt deleted file mode 100644 index 49c5298..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/annotations/ExclusiveAudioCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.audio.exclusiveaudio.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ExclusiveAudioCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/AudioOnlyEnablerFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/AudioOnlyEnablerFingerprint.kt deleted file mode 100644 index 657b1de..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/AudioOnlyEnablerFingerprint.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.music.audio.exclusiveaudio.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("audio-only-enabler-fingerprint") - -@ExclusiveAudioCompatibility -@Version( - "0.0.1" -) -object AudioOnlyEnablerFingerprint: MethodFingerprint( - "Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.GOTO, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.RETURN - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/ExclusiveAudioFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/ExclusiveAudioFingerprint.kt deleted file mode 100644 index fe2f45b..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/fingerprints/ExclusiveAudioFingerprint.kt +++ /dev/null @@ -1,56 +0,0 @@ -package app.revanced.patches.music.audio.exclusiveaudio.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("exclusive-audio-fingerprints") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@ExclusiveAudioCompatibility -@Version("0.0.1") -object ExclusiveAudioFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("L", "Z"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQ, - Opcode.CONST_4, - Opcode.GOTO, - Opcode.NOP, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IF_EQZ, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.INVOKE_INTERFACE, - Opcode.GOTO, - Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt b/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt deleted file mode 100644 index d679e87..0000000 --- a/src/main/kotlin/app/revanced/patches/music/audio/exclusiveaudio/patch/ExclusiveAudioPatch.kt +++ /dev/null @@ -1,33 +0,0 @@ -package app.revanced.patches.music.audio.exclusiveaudio.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.audio.exclusiveaudio.annotations.ExclusiveAudioCompatibility -import app.revanced.patches.music.audio.exclusiveaudio.fingerprints.AudioOnlyEnablerFingerprint - -@Patch -@Name("exclusive-audio-playback") -@Description("Enables the option to play music without video.") -@ExclusiveAudioCompatibility -@Version("0.0.1") -class ExclusiveAudioPatch : BytecodePatch( - listOf( - AudioOnlyEnablerFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = AudioOnlyEnablerFingerprint.result!!.mutableMethod - method.replaceInstruction(method.implementation!!.instructions.count() - 1, "const/4 v0, 0x1") - method.addInstruction("return v0") - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt deleted file mode 100644 index a18799e..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/annotations/CompactHeaderCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.layout.compactheader.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CompactHeaderCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt deleted file mode 100644 index 8a1e7f8..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/fingerprints/CompactHeaderConstructorFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.music.layout.compactheader.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.layout.compactheader.annotations.CompactHeaderCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("compact-header-constructor-fingerprint") -@CompactHeaderCompatibility -@Version("0.0.1") -object CompactHeaderConstructorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt deleted file mode 100644 index 879dfa0..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/compactheader/patch/CompactHeaderPatch.kt +++ /dev/null @@ -1,41 +0,0 @@ -package app.revanced.patches.music.layout.compactheader.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.layout.compactheader.annotations.CompactHeaderCompatibility -import app.revanced.patches.music.layout.compactheader.fingerprints.CompactHeaderConstructorFingerprint -import org.jf.dexlib2.builder.instruction.BuilderInstruction11x - -@Patch(false) -@Name("compact-header") -@Description("Hides the music category bar at the top of the homepage.") -@CompactHeaderCompatibility -@Version("0.0.1") -class CompactHeaderPatch : BytecodePatch( - listOf( - CompactHeaderConstructorFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val result = CompactHeaderConstructorFingerprint.result!! - val method = result.mutableMethod - - val insertIndex = result.scanResult.patternScanResult!!.endIndex - val register = (method.implementation!!.instructions[insertIndex - 1] as BuilderInstruction11x).registerA - method.addInstructions( - insertIndex, """ - const/16 v2, 0x8 - invoke-virtual {v${register}, v2}, Landroid/view/View;->setVisibility(I)V - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt deleted file mode 100644 index fd7d6f0..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.layout.minimizedplayback.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MinimizedPlaybackCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt deleted file mode 100644 index f24131e..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt +++ /dev/null @@ -1,32 +0,0 @@ -package app.revanced.patches.music.layout.minimizedplayback.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("minimized-playback-manager-fingerprint") -@MinimizedPlaybackCompatibility -@Version("0.0.1") -object MinimizedPlaybackManagerFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("I", "L", "Z"), - listOf( - Opcode.IGET, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.IF_NE, - Opcode.IGET_BOOLEAN, - Opcode.IF_EQ, - Opcode.GOTO, - Opcode.RETURN_VOID, - Opcode.SGET_OBJECT, - Opcode.CONST_4, - Opcode.IF_NE, - Opcode.IPUT_BOOLEAN, - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt deleted file mode 100644 index dcfdb9f..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/minimizedplayback/patch/MinimizedPlaybackPatch.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.patches.music.layout.minimizedplayback.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.layout.minimizedplayback.annotations.MinimizedPlaybackCompatibility -import app.revanced.patches.music.layout.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint - -@Patch -@Name("minimized-playback-music") -@Description("Enables minimized playback on Kids music.") -@MinimizedPlaybackCompatibility -@Version("0.0.1") -class MinimizedPlaybackPatch : BytecodePatch( - listOf( - MinimizedPlaybackManagerFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions( - 0, """ - return-void - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt deleted file mode 100644 index d37ccf6..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/annotations/HideGetPremiumCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.layout.premium.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideGetPremiumCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt deleted file mode 100644 index 5d03e16..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumFingerprint.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.music.layout.premium.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("hide-get-premium-fingerprint") -@HideGetPremiumCompatibility -@Version("0.0.1") -object HideGetPremiumFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.IF_NEZ, - Opcode.CONST_16, - Opcode.GOTO, - Opcode.NOP, - Opcode.INVOKE_VIRTUAL - ) -) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt deleted file mode 100644 index 5244ab5..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/fingerprints/HideGetPremiumParentFingerprint.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.revanced.patches.music.layout.premium.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("hide-get-premium-parent-fingerprint") -@HideGetPremiumCompatibility -@Version("0.0.1") -object HideGetPremiumParentFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC - ), - listOf("FEmusic_history"), -) diff --git a/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt deleted file mode 100644 index 727ff9d..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/premium/patch/HideGetPremiumPatch.kt +++ /dev/null @@ -1,51 +0,0 @@ -package app.revanced.patches.music.layout.premium.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.layout.premium.annotations.HideGetPremiumCompatibility -import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumFingerprint -import app.revanced.patches.music.layout.premium.fingerprints.HideGetPremiumParentFingerprint - -@Patch -@Name("hide-get-premium") -@Description("Removes all \"Get Premium\" evidences from the avatar menu.") -@HideGetPremiumCompatibility -@Version("0.0.1") -class HideGetPremiumPatch : BytecodePatch( - listOf( - HideGetPremiumParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val parentResult = HideGetPremiumParentFingerprint.result!! - HideGetPremiumFingerprint.resolve(context, parentResult.classDef) - - val startIndex = parentResult.scanResult.patternScanResult!!.startIndex - - val parentMethod = parentResult.mutableMethod - parentMethod.replaceInstruction( - startIndex, """ - const/4 v1, 0x0 - """ - ) - - val result = HideGetPremiumFingerprint.result!! - val method = result.mutableMethod - method.addInstructions( - startIndex, """ - const/16 v0, 0x8 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt deleted file mode 100644 index 3332338..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/annotations/RemoveTasteBuilderCompatibility.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.music.layout.tastebuilder.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -/** - * -- Note 2022-08-05 -- - * Since 5.17.xx the tastebuilder component is dismissible, so this patch is less useful - * also it is partly litho now - */ -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class RemoveTasteBuilderCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt deleted file mode 100644 index db9133a..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/fingerprints/TasteBuilderConstructorFingerprint.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.revanced.patches.music.layout.tastebuilder.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("taste-builder-constructor-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@RemoveTasteBuilderCompatibility -@Version("0.0.1") -object TasteBuilderConstructorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_VIRTUAL, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.CONST - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt deleted file mode 100644 index d3b61a3..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/tastebuilder/patch/RemoveTasteBuilderPatch.kt +++ /dev/null @@ -1,41 +0,0 @@ -package app.revanced.patches.music.layout.tastebuilder.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.layout.tastebuilder.annotations.RemoveTasteBuilderCompatibility -import app.revanced.patches.music.layout.tastebuilder.fingerprints.TasteBuilderConstructorFingerprint -import org.jf.dexlib2.iface.instruction.formats.Instruction22c - -@Patch -@Name("tasteBuilder-remover") -@Description("Removes the \"Tell us which artists you like\" card from the home screen.") -@RemoveTasteBuilderCompatibility -@Version("0.0.1") -class RemoveTasteBuilderPatch : BytecodePatch( - listOf( - TasteBuilderConstructorFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val result = TasteBuilderConstructorFingerprint.result!! - val method = result.mutableMethod - - val insertIndex = result.scanResult.patternScanResult!!.endIndex - 8 - val register = (method.implementation!!.instructions[insertIndex] as Instruction22c).registerA - method.addInstructions( - insertIndex, """ - const/16 v1, 0x8 - invoke-virtual {v${register}, v1}, Landroid/view/View;->setVisibility(I)V - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt deleted file mode 100644 index f14ffa2..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/annotations/RemoveUpgradeButtonCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.layout.upgradebutton.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class RemoveUpgradeButtonCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt deleted file mode 100644 index 43f2edd..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/fingerprints/PivotBarConstructorFingerprint.kt +++ /dev/null @@ -1,67 +0,0 @@ -package app.revanced.patches.music.layout.upgradebutton.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("pivot-bar-constructor-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@RemoveUpgradeButtonCompatibility -@Version("0.0.1") -object PivotBarConstructorFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - listOf("L", "Z"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.CONST_4, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_BOOLEAN, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.GOTO, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_INTERFACE, - Opcode.GOTO, - Opcode.NOP, - Opcode.IPUT_OBJECT, - Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt b/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt deleted file mode 100644 index 9bf8ad0..0000000 --- a/src/main/kotlin/app/revanced/patches/music/layout/upgradebutton/patch/RemoveUpgradeButtonPatch.kt +++ /dev/null @@ -1,78 +0,0 @@ -package app.revanced.patches.music.layout.upgradebutton.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.toInstructions -import app.revanced.patches.music.layout.upgradebutton.annotations.RemoveUpgradeButtonCompatibility -import app.revanced.patches.music.layout.upgradebutton.fingerprints.PivotBarConstructorFingerprint -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction22t -import org.jf.dexlib2.iface.instruction.formats.Instruction22c -import org.jf.dexlib2.iface.instruction.formats.Instruction35c - - -@Patch -@Name("upgrade-button-remover") -@Description("Removes the upgrade tab from the pivot bar.") -@RemoveUpgradeButtonCompatibility -@Version("0.0.1") -class RemoveUpgradeButtonPatch : BytecodePatch( - listOf( - PivotBarConstructorFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val result = PivotBarConstructorFingerprint.result!! - val implementation = result.mutableMethod.implementation!! - - val pivotBarElementFieldRef = - (implementation.instructions[result.scanResult.patternScanResult!!.endIndex - 1] as Instruction22c).reference - - val register = (implementation.instructions.first() as Instruction35c).registerC - // first compile all the needed instructions - val instructionList = """ - invoke-interface { v0 }, Ljava/util/List;->size()I - move-result v1 - const/4 v2, 0x3 - invoke-interface {v0, v2}, Ljava/util/List;->remove(I)Ljava/lang/Object; - iput-object v0, v$register, $pivotBarElementFieldRef - """.toInstructions().toMutableList() - - - val endIndex = result.scanResult.patternScanResult!!.endIndex - - // replace the instruction to retain the label at given index - implementation.replaceInstruction( - endIndex - 1, instructionList[0] // invoke-interface - ) - // do not forget to remove this instruction since we added it already - instructionList.removeFirst() - - val exitInstruction = instructionList.last() // iput-object - implementation.addInstruction( - endIndex, exitInstruction - ) - // do not forget to remove this instruction since we added it already - instructionList.removeLast() - - // add the necessary if statement to remove the upgrade tab button in case it exists - instructionList.add( - 2, // if-le - BuilderInstruction22t( - Opcode.IF_LE, 1, 2, implementation.newLabelForIndex(endIndex) - ) - ) - - implementation.addInstructions( - endIndex, instructionList - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt deleted file mode 100644 index 6ce2b6b..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/annotations/MusicMicroGPatchCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.misc.microg.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MusicMicroGPatchCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt deleted file mode 100644 index 0ddd7e0..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastContextFetchFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("cast-context-fetch-fingerprint") - -@MicroGPatchCompatibility -@Version("0.0.1") -object CastContextFetchFingerprint : MethodFingerprint( - strings = listOf("Error fetching CastContext.") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt deleted file mode 100644 index 0259d0f..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("cast-module-fingerprint") - -@MicroGPatchCompatibility -@Version("0.0.1") -object CastDynamiteModuleFingerprint : MethodFingerprint( - strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt deleted file mode 100644 index 981b3db..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("cast-context-fetch-fingerprint") - -@MicroGPatchCompatibility -@Version("0.0.1") -object CastDynamiteModuleV2Fingerprint : MethodFingerprint( - strings = listOf("Failed to load module via V2: ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt deleted file mode 100644 index cfde192..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("google-play-utility-fingerprint") - -@MusicMicroGPatchCompatibility -@Version("0.0.1") -object GooglePlayUtilityFingerprint : MethodFingerprint( - "I", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L", "I"), - strings = listOf( - "This should never happen.", - "MetadataValueReader", - "GooglePlayServicesUtil", - "com.android.vending", - "android.hardware.type.embedded" - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt deleted file mode 100644 index d274697..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/PrimeFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility - -@Name("google-play-prime-fingerprint") - -@MusicMicroGPatchCompatibility -@Version("0.0.1") -object PrimeFingerprint : MethodFingerprint( - strings = listOf("com.google.android.GoogleCamera", "com.android.vending") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt deleted file mode 100644 index 7e66bab..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/fingerprints/ServiceCheckFingerprint.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.music.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("google-play-service-checker-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@MusicMicroGPatchCompatibility -@Version("0.0.1") -object ServiceCheckFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L", "I"), - strings = listOf("Google Play Services not available") -) diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt deleted file mode 100644 index 07b99c3..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/bytecode/MusicMicroGBytecodePatch.kt +++ /dev/null @@ -1,65 +0,0 @@ -package app.revanced.patches.music.misc.microg.patch.bytecode - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility -import app.revanced.patches.music.misc.microg.fingerprints.* -import app.revanced.patches.music.misc.microg.patch.resource.MusicMicroGResourcePatch -import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants -import app.revanced.util.microg.MicroGBytecodeHelper - -@Patch -@DependsOn([MusicMicroGResourcePatch::class]) -@Name("music-microg-support") -@Description("Allows YouTube Music ReVanced to run without root and under a different package name.") -@MusicMicroGPatchCompatibility -@Version("0.0.2") -class MusicMicroGBytecodePatch : BytecodePatch( - listOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint, - PrimeFingerprint, - ) -) { - // NOTE: the previous patch also replaced the following strings, but it seems like they are not needed: - // - "com.google.android.gms.chimera.GmsIntentOperationService", - // - "com.google.android.gms.phenotype.internal.IPhenotypeCallbacks", - // - "com.google.android.gms.phenotype.internal.IPhenotypeService", - // - "com.google.android.gms.phenotype.PACKAGE_NAME", - // - "com.google.android.gms.phenotype.UPDATE", - // - "com.google.android.gms.phenotype", - override fun execute(context: BytecodeContext) = - // apply common microG patch - MicroGBytecodeHelper.patchBytecode( - context, - arrayOf( - MicroGBytecodeHelper.packageNameTransform( - Constants.PACKAGE_NAME, - Constants.REVANCED_PACKAGE_NAME - ) - ), - MicroGBytecodeHelper.PrimeMethodTransformationData( - PrimeFingerprint, - MUSIC_PACKAGE_NAME, - REVANCED_MUSIC_PACKAGE_NAME - ), - listOf( - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint - ) - ).let { PatchResultSuccess() } -} diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt deleted file mode 100644 index 19daba3..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/patch/resource/MusicMicroGResourcePatch.kt +++ /dev/null @@ -1,41 +0,0 @@ -package app.revanced.patches.music.misc.microg.patch.resource - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patches.music.misc.microg.annotations.MusicMicroGPatchCompatibility -import app.revanced.patches.music.misc.microg.shared.Constants.MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_APP_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.REVANCED_MUSIC_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME -import app.revanced.patches.music.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE -import app.revanced.util.microg.MicroGManifestHelper -import app.revanced.util.microg.MicroGResourceHelper - -@Name("music-microg-resource-patch") -@Description("Resource patch to allow YouTube Music ReVanced to run without root and under a different package name.") -@MusicMicroGPatchCompatibility -@Version("0.0.2") -class MusicMicroGResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - // update manifest - MicroGResourceHelper.patchManifest( - context, - MUSIC_PACKAGE_NAME, - REVANCED_MUSIC_PACKAGE_NAME, - REVANCED_MUSIC_APP_NAME - ) - - // add metadata to the manifest - MicroGManifestHelper.addSpoofingMetadata( - context, - SPOOFED_PACKAGE_NAME, - SPOOFED_PACKAGE_SIGNATURE - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt b/src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt deleted file mode 100644 index a7405cc..0000000 --- a/src/main/kotlin/app/revanced/patches/music/misc/microg/shared/Constants.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.music.misc.microg.shared - -object Constants { - internal const val REVANCED_MUSIC_APP_NAME = "YT Music ReVanced" - internal const val REVANCED_MUSIC_PACKAGE_NAME = "app.revanced.android.apps.youtube.music" - internal const val MUSIC_PACKAGE_NAME = "com.google.android.apps.youtube.music" - internal const val SPOOFED_PACKAGE_NAME = MUSIC_PACKAGE_NAME - internal const val SPOOFED_PACKAGE_SIGNATURE = "afb0fed5eeaebdd86f56a97742f4b6b33ef59875" -} diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt deleted file mode 100644 index 54a5527..0000000 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/annotations/BackgroundPlayCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.music.premium.backgroundplay.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.apps.youtube.music", arrayOf("5.14.53", "5.16.51", "5.17.51", "5.21.52", "5.22.54", "5.23.50", "5.25.51", "5.25.52", "5.26.52", "5.27.51", "5.28.52", "5.29.52", "5.31.50") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class BackgroundPlayCompatibility diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt deleted file mode 100644 index c8150ca..0000000 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/fingerprints/BackgroundPlaybackDisableFingerprint.kt +++ /dev/null @@ -1,48 +0,0 @@ -package app.revanced.patches.music.premium.backgroundplay.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("background-playback-disabler-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@BackgroundPlayCompatibility -@Version("0.0.1") -object BackgroundPlaybackDisableFingerprint : MethodFingerprint( - "Z", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf( - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET, - Opcode.AND_INT_LIT16, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_BOOLEAN, - Opcode.IF_EQZ, - Opcode.CONST_4, - Opcode.RETURN, - Opcode.RETURN, - Opcode.RETURN - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt b/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt deleted file mode 100644 index 9c860a9..0000000 --- a/src/main/kotlin/app/revanced/patches/music/premium/backgroundplay/patch/BackgroundPlayPatch.kt +++ /dev/null @@ -1,36 +0,0 @@ -package app.revanced.patches.music.premium.backgroundplay.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.music.premium.backgroundplay.annotations.BackgroundPlayCompatibility -import app.revanced.patches.music.premium.backgroundplay.fingerprints.BackgroundPlaybackDisableFingerprint - -@Patch -@Name("background-play") -@Description("Enables playing music in the background.") -@BackgroundPlayCompatibility -@Version("0.0.1") -class BackgroundPlayPatch : BytecodePatch( - listOf( - BackgroundPlaybackDisableFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - BackgroundPlaybackDisableFingerprint.result!!.mutableMethod.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt deleted file mode 100644 index 39c9434..0000000 --- a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/annotations/UnlockProCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.nyx.misc.pro.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.awedea.nyx")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class UnlockProCompatibility diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt deleted file mode 100644 index 4d2d13a..0000000 --- a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/fingerprints/CheckProFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.nyx.misc.pro.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.nyx.misc.pro.annotations.UnlockProCompatibility - -@Name("check-pro-fingerprint") -@UnlockProCompatibility -@Version("0.0.1") -object CheckProFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("BillingManager;") && methodDef.name == "isProVersion" - } -) diff --git a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt b/src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt deleted file mode 100644 index bb0ee59..0000000 --- a/src/main/kotlin/app/revanced/patches/nyx/misc/pro/patch/UnlockProPatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.nyx.misc.pro.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.nyx.misc.pro.annotations.UnlockProCompatibility -import app.revanced.patches.nyx.misc.pro.fingerprints.CheckProFingerprint - -@Patch -@Name("unlock-pro") -@Description("Unlocks all pro features.") -@UnlockProCompatibility -@Version("0.0.1") -class UnlockProPatch : BytecodePatch( - listOf( - CheckProFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = CheckProFingerprint.result!!.mutableMethod - method.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt deleted file mode 100644 index 0666c87..0000000 --- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/annotations/GeneralAdsCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.reddit.ad.general.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.reddit.frontpage")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class GeneralAdsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt deleted file mode 100644 index 86341a6..0000000 --- a/src/main/kotlin/app/revanced/patches/reddit/ad/general/patch/GeneralAdsPatch.kt +++ /dev/null @@ -1,54 +0,0 @@ -package app.revanced.patches.reddit.ad.general.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.reddit.ad.general.annotations.GeneralAdsCompatibility -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21c -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.StringReference -import org.jf.dexlib2.immutable.reference.ImmutableStringReference - -@Patch -@Name("general-reddit-ads") -@Description("Removes general ads from the Reddit frontpage and subreddits.") -@GeneralAdsCompatibility -@Version("0.0.1") -class GeneralAdsPatch : BytecodePatch() { - override fun execute(context: BytecodeContext): PatchResult { - context.classes.forEach { classDef -> - classDef.methods.forEach methodLoop@{ method -> - val implementation = method.implementation ?: return@methodLoop - - implementation.instructions.forEachIndexed { i, instruction -> - if (instruction.opcode != Opcode.CONST_STRING) return@forEachIndexed - if (((instruction as ReferenceInstruction).reference as StringReference).string != "AdPost") return@forEachIndexed - - val proxiedClass = context.proxy(classDef).mutableClass - - val proxiedImplementation = proxiedClass.methods.first { - it.name == method.name && it.parameterTypes.containsAll(method.parameterTypes) - }.implementation!! - - var newString = "AdPost1" - if (proxiedImplementation.instructions[i - 1].opcode == Opcode.CONST_STRING) { - newString = "SubredditPost" - } - proxiedImplementation.replaceInstruction( - i, BuilderInstruction21c( - Opcode.CONST_STRING, (proxiedImplementation.instructions[i] as BuilderInstruction21c).registerA, ImmutableStringReference(newString) - ) - ) - } - } - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt deleted file mode 100644 index 11ea3c8..0000000 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/annotations/PremiumIconCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.reddit.layout.premiumicon.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.reddit.frontpage")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PremiumIconCompatibility diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt deleted file mode 100644 index 3eb53af..0000000 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/fingerprints/PremiumIconFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.reddit.layout.premiumicon.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.reddit.layout.premiumicon.annotations.PremiumIconCompatibility - -@Name("premium-icon-fingerprint") -@PremiumIconCompatibility -@Version("0.0.1") -object PremiumIconFingerprint : MethodFingerprint( - "Z", - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("MyAccount;") && methodDef.name == "isPremiumSubscriber" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt b/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt deleted file mode 100644 index 156c746..0000000 --- a/src/main/kotlin/app/revanced/patches/reddit/layout/premiumicon/patch/PremiumIconPatch.kt +++ /dev/null @@ -1,36 +0,0 @@ -package app.revanced.patches.reddit.layout.premiumicon.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.reddit.layout.premiumicon.annotations.PremiumIconCompatibility -import app.revanced.patches.reddit.layout.premiumicon.fingerprints.PremiumIconFingerprint - -@Patch -@Name("premium-icon-reddit") -@Description("Unlocks premium Reddit app icons.") -@PremiumIconCompatibility -@Version("0.0.1") -class PremiumIconPatch : BytecodePatch( - listOf( - PremiumIconFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = PremiumIconFingerprint.result!!.mutableMethod - method.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt deleted file mode 100644 index 3aad515..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/audio/annotation/DisableCaptureRestrictionCompatibility.kt +++ /dev/null @@ -1,12 +0,0 @@ -package app.revanced.patches.spotify.audio.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package("com.spotify.music")] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DisableCaptureRestrictionCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt deleted file mode 100644 index 88aae6a..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/audio/bytecode/patch/DisableCaptureRestrictionBytecodePatch.kt +++ /dev/null @@ -1,86 +0,0 @@ -package app.revanced.patches.spotify.audio.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility -import app.revanced.patches.spotify.audio.fingerprints.DisableCaptureRestrictionAudioDriverFingerprint -import app.revanced.patches.spotify.audio.resource.patch.DisableCaptureRestrictionResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.MethodReference - -@Patch -@Name("disable-capture-restriction") -@DependsOn([DisableCaptureRestrictionResourcePatch::class]) -@Description("Allows capturing Spotify's audio output while screen sharing or screen recording.") -@DisableCaptureRestrictionCompatibility -@Version("0.0.2") -class DisableCaptureRestrictionBytecodePatch : BytecodePatch( - listOf( - DisableCaptureRestrictionAudioDriverFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = DisableCaptureRestrictionAudioDriverFingerprint.result!!.mutableMethod - - var invokePosition: Int? = null - var invokeParamRegister: Int? = null - - // Find INVOKE_VIRTUAL opcode with call to AudioAttributesBuilder.setAllowedCapturePolicy(I) - for ((index, instruction) in method.implementation!!.instructions.withIndex()) { - if(instruction.opcode != Opcode.INVOKE_VIRTUAL) - continue - - val methodName = ((instruction as ReferenceInstruction).reference as MethodReference).name - if (methodName != "setAllowedCapturePolicy") - continue - - // Store register of the integer parameter for setAllowedCapturePolicy - invokeParamRegister = (instruction as FiveRegisterInstruction).registerD - invokePosition = index - } - - if(invokePosition == null || invokeParamRegister == null) - return PatchResultError("Cannot find setAllowedCapturePolicy method call") - - // Walk back to the const/4 instruction that sets the parameter register - var matchFound = false - for (index in invokePosition downTo 0) { - val instruction = method.instruction(index) - if(instruction.opcode != Opcode.CONST_4) - continue - - val register = (instruction as OneRegisterInstruction).registerA - if(register != invokeParamRegister) - continue - - // Replace parameter value - method.replaceInstruction( - index, "const/4 v$register, $ALLOW_CAPTURE_BY_ALL" - ) - matchFound = true - break - } - - return if (matchFound) - PatchResultSuccess() - else - PatchResultError("Const instruction not found") - } - - private companion object { - const val ALLOW_CAPTURE_BY_ALL = 0x01 - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt deleted file mode 100644 index cf500b8..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/audio/fingerprints/DisableCaptureRestrictionAudioDriverFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.spotify.audio.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility - -@Name("disable-capture-restriction-audio-driver-fingerprint") - -@DisableCaptureRestrictionCompatibility -@Version("0.0.2") -object DisableCaptureRestrictionAudioDriverFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass == "Lcom/spotify/playback/playbacknative/AudioDriver;" && methodDef.name == "constructAudioAttributes" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt deleted file mode 100644 index 5088cce..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/audio/resource/patch/DisableCaptureRestrictionResourcePatch.kt +++ /dev/null @@ -1,33 +0,0 @@ -package app.revanced.patches.spotify.audio.resource.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patches.spotify.audio.annotation.DisableCaptureRestrictionCompatibility -import org.w3c.dom.Element - -@Name("disable-capture-restriction-resource-patch") -@Description("Sets allowAudioPlaybackCapture in manifest to true.") -@DisableCaptureRestrictionCompatibility -@Version("0.0.2") -class DisableCaptureRestrictionResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - // create an xml editor instance - context.xmlEditor["AndroidManifest.xml"].use { dom -> - // get the application node - val applicationNode = dom - .file - .getElementsByTagName("application") - .item(0) as Element - - // set allowAudioPlaybackCapture attribute to true - applicationNode.setAttribute("android:allowAudioPlaybackCapture", "true") - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt deleted file mode 100644 index bc24c39..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/annotations/ThemeCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.spotify.layout.theme.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.spotify.music")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ThemeCompatibility diff --git a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt b/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt deleted file mode 100644 index dfbc7fd..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/layout/theme/patch/ThemePatch.kt +++ /dev/null @@ -1,66 +0,0 @@ -package app.revanced.patches.spotify.layout.theme.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.spotify.layout.theme.annotations.ThemeCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import org.w3c.dom.Element - -@Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) -@Name("spotify-theme") -@Description("Applies a custom theme.") -@ThemeCompatibility -@Version("0.0.1") -class ThemePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - context.xmlEditor["res/values/colors.xml"].use { editor -> - val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element - - for (i in 0 until resourcesNode.childNodes.length) { - val node = resourcesNode.childNodes.item(i) as? Element ?: continue - - node.textContent = when (node.getAttribute("name")) { - "gray_7" -> backgroundColor!! - "dark_brightaccent_background_base", "dark_base_text_brightaccent", "green_light" -> accentColor!! - "dark_brightaccent_background_press" -> accentPressedColor!! - else -> continue - } - } - } - - return PatchResultSuccess() - } - - companion object : OptionsContainer() { - var backgroundColor: String? by option( - PatchOption.StringOption( - key = "backgroundColor", - default = "@android:color/black", - title = "Background color", - description = "The background color. Can be a hex color or a resource reference.", - ) - ) - var accentColor: String? by option( - PatchOption.StringOption( - key = "accentColor", - default = "#ff1ed760", - title = "Accent color", - description = "The accent color ('spotify green' by default). Can be a hex color or a resource reference.", - ) - ) - var accentPressedColor: String? by option( - PatchOption.StringOption( - key = "accentPressedColor", - default = "#ff169c46", - title = "Pressed accent for the dark theme", - description = "The color when accented buttons are pressed, by default slightly darker than accent. Can be a hex color or a resource reference.", - ) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt b/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt deleted file mode 100644 index 41f6531..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/annotations/PremiumNavbarTabCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.spotify.premium_navbar_tab.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.spotify.music")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PremiumNavbarTabCompatibility diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt deleted file mode 100644 index a0d5bf0..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.spotify.premium_navbar_tab.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.spotify.premium_navbar_tab.annotations.PremiumNavbarTabCompatibility - -@Name("premium-navbar-fingerprint") -@Version("0.0.1") -@PremiumNavbarTabCompatibility -object AddPremiumNavbarTabFingerprint : MethodFingerprint( - parameters = listOf("L", "L", "L", "L", "L", "L") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt deleted file mode 100644 index cfff25e..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/fingerprints/AddPremiumNavbarTabParentFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.spotify.premium_navbar_tab.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.spotify.premium_navbar_tab.annotations.PremiumNavbarTabCompatibility - -@Name("add-premium-navbar-tab-parent-fingerprint") -@Version("0.0.1") -@PremiumNavbarTabCompatibility -object AddPremiumNavbarTabParentFingerprint : MethodFingerprint( - strings = listOf("com.samsung.android.samsungaccount.action.REQUEST_AUTHCODE") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt b/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt deleted file mode 100644 index 4c992bb..0000000 --- a/src/main/kotlin/app/revanced/patches/spotify/premium_navbar_tab/patch/PremiumNavbarTabPatch.kt +++ /dev/null @@ -1,63 +0,0 @@ -package app.revanced.patches.spotify.premium_navbar_tab.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.spotify.premium_navbar_tab.annotations.PremiumNavbarTabCompatibility -import app.revanced.patches.spotify.premium_navbar_tab.fingerprints.AddPremiumNavbarTabFingerprint -import app.revanced.patches.spotify.premium_navbar_tab.fingerprints.AddPremiumNavbarTabParentFingerprint -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Patch -@Name("hide-premium-navbar") -@Description("Removes the premium tab from the navbar.") -@PremiumNavbarTabCompatibility -@Version("0.0.1") -@DependsOn([ResourceMappingResourcePatch::class]) -class PremiumNavbarTabPatch : BytecodePatch( - listOf( - AddPremiumNavbarTabParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val parentResult = AddPremiumNavbarTabParentFingerprint.result!! - AddPremiumNavbarTabFingerprint.resolve(context, parentResult.classDef) - - val result = AddPremiumNavbarTabFingerprint.result!! - - val method = result.mutableMethod - val methodInstructions = method.implementation!!.instructions - val lastInstructionIdx = methodInstructions.size - 1 - - val premiumTabId = - ResourceMappingResourcePatch.resourceMappings.single { it.type == "id" && it.name == "premium_tab" }.id - - var removeAmount = 2 - // 2nd const remove method - for ((i, instruction) in methodInstructions.asReversed().withIndex()) { - if (instruction.opcode.ordinal != Opcode.CONST.ordinal) continue - if ((instruction as WideLiteralInstruction).wideLiteral != premiumTabId) continue - - val findThreshold = 10 - val constIndex = lastInstructionIdx - i - val invokeInstruction = methodInstructions.subList(constIndex, constIndex + findThreshold).first { - it.opcode.ordinal == Opcode.INVOKE_VIRTUAL_RANGE.ordinal - } - method.removeInstruction(methodInstructions.indexOf(invokeInstruction)) - - if (--removeAmount == 0) break - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt deleted file mode 100644 index cc09664..0000000 --- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/annotations/UnlockThemesCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.ticktick.misc.themeunlock.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.ticktick.task")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class UnlockThemesCompatibility diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt deleted file mode 100644 index 0d6f167..0000000 --- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/CheckLockedThemesFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.ticktick.misc.themeunlock.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.ticktick.misc.themeunlock.annotations.UnlockThemesCompatibility - -@Name("check-locked-theme-fingerprint") -@UnlockThemesCompatibility -@Version("0.0.1") -object CheckLockedThemesFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("Theme;") && methodDef.name == "isLockedTheme" - } -) diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt deleted file mode 100644 index d9d3dc4..0000000 --- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/fingerprints/SetThemeFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.ticktick.misc.themeunlock.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.ticktick.misc.themeunlock.annotations.UnlockThemesCompatibility - -@Name("set-theme-fingerprint") -@UnlockThemesCompatibility -@Version("0.0.1") -object SetThemeFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("ThemePreviewActivity;") && methodDef.name == "lambda\$updateUserBtn\$1" - } -) diff --git a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt b/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt deleted file mode 100644 index e1b6664..0000000 --- a/src/main/kotlin/app/revanced/patches/ticktick/misc/themeunlock/patch/UnlockThemePatch.kt +++ /dev/null @@ -1,43 +0,0 @@ -package app.revanced.patches.ticktick.misc.themeunlock.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.ticktick.misc.themeunlock.annotations.UnlockThemesCompatibility -import app.revanced.patches.ticktick.misc.themeunlock.fingerprints.CheckLockedThemesFingerprint -import app.revanced.patches.ticktick.misc.themeunlock.fingerprints.SetThemeFingerprint - -@Patch -@Name("unlock-themes") -@Description("Unlocks all themes.") -@UnlockThemesCompatibility -@Version("0.0.1") -class UnlockProPatch : BytecodePatch( - listOf( - CheckLockedThemesFingerprint, - SetThemeFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val lockedThemesMethod = CheckLockedThemesFingerprint.result!!.mutableMethod - lockedThemesMethod.addInstructions( - 0, - """ - const/4 v0, 0x0 - return v0 - """ - ) - - val setThemeMethod = SetThemeFingerprint.result!!.mutableMethod - setThemeMethod.removeInstructions(0, 9) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/TiktokAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/TiktokAdsCompatibility.kt deleted file mode 100644 index f9a1089..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/ad/annotations/TiktokAdsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.ad.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class TiktokAdsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt deleted file mode 100644 index e3c6d4b..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/ConvertHelpFeedItemListFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.ad.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.ad.annotations.TiktokAdsCompatibility - -@Name("convert-help-v2-feeditemlist-fingerprint") -@TiktokAdsCompatibility -@Version("0.0.1") -object ConvertHelpFeedItemListFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/ConvertHelp;") && - methodDef.name.endsWith("${'$'}FeedItemList") - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt deleted file mode 100644 index 7b2e3e0..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/ad/fingerprints/FeedItemListCloneFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.tiktok.ad.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.ad.annotations.TiktokAdsCompatibility - -@Name("feed-item-clone-fingerprint") -@TiktokAdsCompatibility -@Version("0.0.1") -object FeedItemListCloneFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/FeedItemList;") && methodDef.name == "clone" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/ad/patch/TiktokAdsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/ad/patch/TiktokAdsPatch.kt deleted file mode 100644 index b79f994..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/ad/patch/TiktokAdsPatch.kt +++ /dev/null @@ -1,57 +0,0 @@ -package app.revanced.patches.tiktok.ad.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tiktok.ad.annotations.TiktokAdsCompatibility -import app.revanced.patches.tiktok.ad.fingerprints.ConvertHelpFeedItemListFingerprint -import app.revanced.patches.tiktok.ad.fingerprints.FeedItemListCloneFingerprint -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.reference.FieldReference - -@Patch -@Name("tiktok-ads") -@Description("Removes ads from TikTok.") -@TiktokAdsCompatibility -@Version("0.0.1") -class TiktokAdsPatch : BytecodePatch( - listOf( - FeedItemListCloneFingerprint, - ConvertHelpFeedItemListFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - listOf( - FeedItemListCloneFingerprint, - ConvertHelpFeedItemListFingerprint - ).forEach { fingerprint -> - val method = fingerprint.result!!.mutableMethod - // iterate all instructions in the clone method - for ((index, instruction) in method.implementation!!.instructions.withIndex()) { - // conditions for the instruction we need - if (instruction.opcode.ordinal != Opcode.IPUT_OBJECT.ordinal) continue - val preloadAdsFieldInstruction = (instruction as? ReferenceInstruction) - if ((preloadAdsFieldInstruction?.reference as? FieldReference)?.name != "preloadAds") continue - - // set null instead of the field "preloadAds" - val overrideRegister = (preloadAdsFieldInstruction as TwoRegisterInstruction).registerA - method.addInstruction( - index, - "const/4 v$overrideRegister, 0x0" - ) - return@forEach - } - return PatchResultError("Can not find required instruction.") - } - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt deleted file mode 100644 index d33f698..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/annotations/FeedFilterCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.feedfilter.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class FeedFilterCompatibility diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt deleted file mode 100644 index 8a17f48..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/fingerprints/FeedApiServiceLIZFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.tiktok.feedfilter.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.feedfilter.annotations.FeedFilterCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("feed-api-service-fingerprint") -@FeedFilterCompatibility -@Version("0.0.1") -object FeedApiServiceLIZFingerprint : MethodFingerprint( - access = AccessFlags.PUBLIC or AccessFlags.STATIC or AccessFlags.FINAL or AccessFlags.SYNTHETIC, - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/FeedApiService;") && methodDef.name == "LIZ" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt b/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt deleted file mode 100644 index 1717e9a..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/feedfilter/patch/TiktokFeedFilter.kt +++ /dev/null @@ -1,51 +0,0 @@ -package app.revanced.patches.tiktok.feedfilter.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tiktok.feedfilter.annotations.FeedFilterCompatibility -import app.revanced.patches.tiktok.feedfilter.fingerprints.FeedApiServiceLIZFingerprint -import app.revanced.patches.tiktok.misc.integrations.patch.TikTokIntegrationsPatch -import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint -import app.revanced.patches.tiktok.misc.settings.patch.TikTokSettingsPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([TikTokIntegrationsPatch::class, TikTokSettingsPatch::class]) -@Name("tiktok-feed-filter") -@Description("Filters tiktok videos: removing ads, removing livestreams.") -@FeedFilterCompatibility -@Version("0.0.1") -class TiktokFeedFilter : BytecodePatch( - listOf( - FeedApiServiceLIZFingerprint, - SettingsStatusLoadFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method = FeedApiServiceLIZFingerprint.result!!.mutableMethod - for ((index, instruction) in method.implementation!!.instructions.withIndex()) { - if (instruction.opcode != Opcode.RETURN_OBJECT) continue - val feedItemsRegister = (instruction as OneRegisterInstruction).registerA - method.addInstruction( - index, - "invoke-static {v$feedItemsRegister}, Lapp/revanced/tiktok/feedfilter/FeedItemsFilter;->filter(Lcom/ss/android/ugc/aweme/feed/model/FeedItemList;)V" - ) - break - } - val method2 = SettingsStatusLoadFingerprint.result!!.mutableMethod - method2.addInstruction( - 0, - "invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableFeedFilter()V" - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt deleted file mode 100644 index 2a353e8..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/annotations/DownloadsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.interaction.downloads.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DownloadsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt deleted file mode 100644 index a6a5333..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.tiktok.interaction.downloads.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("acl-common-share-get-code") -@DownloadsCompatibility -@Version("0.0.1") -object ACLCommonShareFingerprint : MethodFingerprint( - "I", - AccessFlags.PUBLIC or AccessFlags.FINAL, - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/ACLCommonShare;") && - methodDef.name == "getCode" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt deleted file mode 100644 index 384530d..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint2.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.tiktok.interaction.downloads.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("acl-common-share-get-show-type") -@DownloadsCompatibility -@Version("0.0.1") -object ACLCommonShareFingerprint2 : MethodFingerprint( - "I", - AccessFlags.PUBLIC or AccessFlags.FINAL, - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/ACLCommonShare;") && - methodDef.name == "getShowType" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt deleted file mode 100644 index cf585dd..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/ACLCommonShareFingerprint3.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.tiktok.interaction.downloads.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("acl-common-share-get-transcode") -@DownloadsCompatibility -@Version("0.0.1") -object ACLCommonShareFingerprint3 : MethodFingerprint( - "I", - AccessFlags.PUBLIC or AccessFlags.FINAL, - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/ACLCommonShare;") && - methodDef.name == "getTranscode" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/DownloadPathParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/DownloadPathParentFingerprint.kt deleted file mode 100644 index 56d5469..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/fingerprints/DownloadPathParentFingerprint.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.patches.tiktok.interaction.downloads.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("download-path-parent-fingerprint") -@DownloadsCompatibility -@Version("0.0.1") -object DownloadPathParentFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - strings = listOf( - "code", - "reason", - "params insufficient" - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt deleted file mode 100644 index ed5237f..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/downloads/patch/DownloadsPatch.kt +++ /dev/null @@ -1,131 +0,0 @@ -package app.revanced.patches.tiktok.interaction.downloads.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.extensions.replaceInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.tiktok.interaction.downloads.annotations.DownloadsCompatibility -import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint -import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint2 -import app.revanced.patches.tiktok.interaction.downloads.fingerprints.ACLCommonShareFingerprint3 -import app.revanced.patches.tiktok.interaction.downloads.fingerprints.DownloadPathParentFingerprint -import app.revanced.patches.tiktok.misc.integrations.patch.TikTokIntegrationsPatch -import app.revanced.patches.tiktok.misc.settings.fingerprints.SettingsStatusLoadFingerprint -import app.revanced.patches.tiktok.misc.settings.patch.TikTokSettingsPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.StringReference - -@Patch -@DependsOn([TikTokIntegrationsPatch::class, TikTokSettingsPatch::class]) -@Name("tiktok-download") -@Description("Removes download restrictions and changes the default path to download to.") -@DownloadsCompatibility -@Version("0.0.1") -class DownloadsPatch : BytecodePatch( - listOf( - ACLCommonShareFingerprint, - ACLCommonShareFingerprint2, - ACLCommonShareFingerprint3, - DownloadPathParentFingerprint, - SettingsStatusLoadFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val method1 = ACLCommonShareFingerprint.result!!.mutableMethod - method1.replaceInstructions( - 0, - """ - const/4 v0, 0x0 - return v0 - """ - ) - val method2 = ACLCommonShareFingerprint2.result!!.mutableMethod - method2.replaceInstructions( - 0, - """ - const/4 v0, 0x2 - return v0 - """ - ) - //Download videos without watermark. - val method3 = ACLCommonShareFingerprint3.result!!.mutableMethod - method3.addInstructions( - 0, - """ - invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->shouldRemoveWatermark()Z - move-result v0 - if-eqz v0, :noremovewatermark - const/4 v0, 0x1 - return v0 - :noremovewatermark - nop - """ - ) - //Change the download path patch - val method4 = DownloadPathParentFingerprint.result!!.mutableMethod - val implementation4 = method4.implementation - val instructions = implementation4!!.instructions - var targetOffset = -1 - //Search for the target method called instruction offset. - for ((index, instruction) in instructions.withIndex()) { - if (instruction.opcode != Opcode.CONST_STRING) continue - val reference = (instruction as ReferenceInstruction).reference as StringReference - if (reference.string != "video/mp4") continue - val targetInstruction = instructions[index + 1] - if (targetInstruction.opcode != Opcode.INVOKE_STATIC) continue - targetOffset = index + 1 - break - } - if (targetOffset == -1) return PatchResultError("Can not find download path uri method.") - //Change videos' download path. - val downloadUriMethod = context - .toMethodWalker(DownloadPathParentFingerprint.result!!.method) - .nextMethod(targetOffset, true) - .getMethod() as MutableMethod - downloadUriMethod.implementation!!.instructions.forEachIndexed { index, instruction -> - if (instruction.opcode == Opcode.SGET_OBJECT) { - val overrideRegister = (instruction as OneRegisterInstruction).registerA - downloadUriMethod.addInstructions( - index + 1, - """ - invoke-static {}, Lapp/revanced/tiktok/download/DownloadsPatch;->getDownloadPath()Ljava/lang/String; - move-result-object v$overrideRegister - """ - ) - } - if (instruction.opcode == Opcode.CONST_STRING) { - val string = ((instruction as ReferenceInstruction).reference as StringReference).string - if (string.contains("/Camera")) { - val overrideRegister = (instruction as OneRegisterInstruction).registerA - val overrideString = string.replace("/Camera", "") - downloadUriMethod.replaceInstruction( - index, - """ - const-string v$overrideRegister, "$overrideString" - """ - ) - } - } - } - val method5 = SettingsStatusLoadFingerprint.result!!.mutableMethod - method5.addInstruction( - 0, - "invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsStatus;->enableDownload()V" - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/SeekbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/SeekbarCompatibility.kt deleted file mode 100644 index 889f1f8..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/annotations/SeekbarCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.interaction.seekbar.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SeekbarCompatibility diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt deleted file mode 100644 index 00cc753..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/fingerprints/AwemeGetVideoControlFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.tiktok.interaction.seekbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.interaction.seekbar.annotations.SeekbarCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("aweme-get-video-control") -@SeekbarCompatibility -@Version("0.0.1") -object AwemeGetVideoControlFingerprint : MethodFingerprint( - "L", - AccessFlags.PUBLIC.value, - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/Aweme;") && methodDef.name == "getVideoControl" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/TiktokSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/TiktokSeekbarPatch.kt deleted file mode 100644 index 2948263..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/seekbar/patch/TiktokSeekbarPatch.kt +++ /dev/null @@ -1,47 +0,0 @@ -package app.revanced.patches.tiktok.interaction.seekbar.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tiktok.interaction.seekbar.annotations.SeekbarCompatibility -import app.revanced.patches.tiktok.interaction.seekbar.fingerprints.AwemeGetVideoControlFingerprint -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction11n -import org.jf.dexlib2.builder.instruction.BuilderInstruction22c - -@Patch -@Name("tiktok-seekbar") -@Description("Show progress bar for all video.") -@SeekbarCompatibility -@Version("0.0.1") -class TiktokSeekbarPatch : BytecodePatch( - listOf( - AwemeGetVideoControlFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - //Get VideoControl FieldReference - val videoControl = context.findClass { it.type.endsWith("/VideoControl;") } - ?: return PatchResultError("Can not find target class") - val fieldList = videoControl.immutableClass.fields.associateBy { field -> field.name } - - val method = AwemeGetVideoControlFingerprint.result!!.mutableMethod - val implementation = method.implementation!! - implementation.addInstructions( - 1, listOf( - BuilderInstruction11n(Opcode.CONST_4, 1, 1), - BuilderInstruction22c(Opcode.IPUT, 1, 0, fieldList["showProgressBar"]!!), - BuilderInstruction22c(Opcode.IPUT, 1, 0, fieldList["draftProgressBar"]!!) - ) - ) - return PatchResultSuccess() - } - -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/SpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/SpeedCompatibility.kt deleted file mode 100644 index af78df2..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/annotations/SpeedCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.interaction.speed.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SpeedCompatibility diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt deleted file mode 100644 index bdce80e..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/fingerprints/SpeedControlParentFingerprint.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.tiktok.interaction.speed.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.interaction.speed.annotations.SpeedCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("speed-control-parent-fingerprint") -@SpeedCompatibility -@Version("0.0.1") -object SpeedControlParentFingerprint : MethodFingerprint( - returnType = "L", - access = AccessFlags.PRIVATE or AccessFlags.FINAL, - parameters = listOf( - "L" - ), - strings = listOf( - "playback_speed" - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/SpeedPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/SpeedPatch.kt deleted file mode 100644 index 1023fc0..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/interaction/speed/patch/SpeedPatch.kt +++ /dev/null @@ -1,48 +0,0 @@ -package app.revanced.patches.tiktok.interaction.speed.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.tiktok.interaction.speed.annotations.SpeedCompatibility -import app.revanced.patches.tiktok.interaction.speed.fingerprints.SpeedControlParentFingerprint -import org.jf.dexlib2.Opcode - -@Patch -@Name("tiktok-speed") -@Description("Enables the playback speed option for all videos.") -@SpeedCompatibility -@Version("0.0.1") -class SpeedPatch : BytecodePatch( - listOf( - SpeedControlParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val parentMethod = SpeedControlParentFingerprint.result!!.mutableMethod - val parentMethodInstructions = parentMethod.implementation!!.instructions - for ((index, instruction) in parentMethodInstructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) continue - val isSpeedEnableMethod = context - .toMethodWalker(parentMethod) - .nextMethod(index, true) - .getMethod() as MutableMethod - isSpeedEnableMethod.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - break - } - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt deleted file mode 100644 index eaf11e6..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/annotations/DisableForceLoginCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.misc.forcelogin.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DisableForceLoginCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt deleted file mode 100644 index 85bf2f9..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.misc.forcelogin.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.misc.forcelogin.annotations.DisableForceLoginCompatibility - -@Name("mandatory-login-service-fingerprint") -@DisableForceLoginCompatibility -@Version("0.0.1") -object MandatoryLoginServiceFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/MandatoryLoginService;") && - methodDef.name == "enableForcedLogin" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt deleted file mode 100644 index 62eabf3..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/fingerprints/MandatoryLoginServiceFingerprint2.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.misc.forcelogin.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.misc.forcelogin.annotations.DisableForceLoginCompatibility - -@Name("mandatory-login-service-fingerprint2") -@DisableForceLoginCompatibility -@Version("0.0.1") -object MandatoryLoginServiceFingerprint2 : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/MandatoryLoginService;") && - methodDef.name == "shouldShowForcedLogin" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt deleted file mode 100644 index 928c912..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/forcelogin/patch/DisableForceLoginPatch.kt +++ /dev/null @@ -1,43 +0,0 @@ -package app.revanced.patches.tiktok.misc.forcelogin.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tiktok.misc.forcelogin.annotations.DisableForceLoginCompatibility -import app.revanced.patches.tiktok.misc.forcelogin.fingerprints.MandatoryLoginServiceFingerprint -import app.revanced.patches.tiktok.misc.forcelogin.fingerprints.MandatoryLoginServiceFingerprint2 - -@Patch -@Name("tiktok-force-login") -@Description("Do not force login.") -@DisableForceLoginCompatibility -@Version("0.0.1") -class DisableForceLoginPatch : BytecodePatch( - listOf( - MandatoryLoginServiceFingerprint, - MandatoryLoginServiceFingerprint2 - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - listOf( - MandatoryLoginServiceFingerprint, - MandatoryLoginServiceFingerprint2 - ).forEach { fingerprint -> - val method = fingerprint.result!!.mutableMethod - method.addInstructions( - 0, - """ - const/4 v0, 0x0 - return v0 - """ - ) - } - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt deleted file mode 100644 index 5b1c277..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/annotations/TikTokIntegrationsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.misc.integrations.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class TikTokIntegrationsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt deleted file mode 100644 index 1fd49a5..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/fingerprints/InitFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.misc.integrations.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.misc.integrations.annotations.TikTokIntegrationsCompatibility - -@Name("init-fingerprint") -@TikTokIntegrationsCompatibility -@Version("0.0.1") -object InitFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/AwemeHostApplication;") && - methodDef.name == "onCreate" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt deleted file mode 100644 index 79780d1..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/integrations/patch/TikTokIntegrationsPatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.tiktok.misc.integrations.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patches.tiktok.misc.integrations.annotations.TikTokIntegrationsCompatibility -import app.revanced.patches.tiktok.misc.integrations.fingerprints.InitFingerprint - -@Name("tiktok-integrations") -@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") -@TikTokIntegrationsCompatibility -@Version("0.0.1") -class TikTokIntegrationsPatch : BytecodePatch( - listOf( - InitFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - if (context.findClass("Lapp/revanced/tiktok/utils/ReVancedUtils") == null) - return PatchResultError("Integrations have not been merged yet. This patch can not succeed without the integrations.") - val result = InitFingerprint.result!! - - val method = result.mutableMethod - val implementation = method.implementation!! - val count = implementation.registerCount - 1 - - method.addInstruction( - 0, "sput-object v$count, Lapp/revanced/tiktok/utils/ReVancedUtils;->context:Landroid/content/Context;" - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt deleted file mode 100644 index 413a294..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/annotations/TikTokSettingsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.tiktok.misc.settings.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.ss.android.ugc.trill"), - Package("com.zhiliaoapp.musically") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class TikTokSettingsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt deleted file mode 100644 index 66e58eb..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/AdPersonalizationActivityFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.misc.settings.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility - -@Name("ad-personalization-activity-fingerprint") -@TikTokSettingsCompatibility -@Version("0.0.1") -object AdPersonalizationActivityFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/AdPersonalizationActivity;") && - methodDef.name == "onCreate" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt deleted file mode 100644 index c1e8650..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/CopyRightSettingsStringFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.misc.settings.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility - -@Name("copyright-settings-string-fingerprint") -@TikTokSettingsCompatibility -@Version("0.0.1") -object CopyRightSettingsStringFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("/SettingNewVersionFragment;") && - methodDef.name == "onViewCreated" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt deleted file mode 100644 index 7b75995..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/fingerprints/SettingsStatusLoadFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.tiktok.misc.settings.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility - -@Name("settings-status-load-fingerprint") -@TikTokSettingsCompatibility -@Version("0.0.1") -object SettingsStatusLoadFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("Lapp/revanced/tiktok/settingsmenu/SettingsStatus;") && - methodDef.name == "load" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt b/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt deleted file mode 100644 index 5e71227..0000000 --- a/src/main/kotlin/app/revanced/patches/tiktok/misc/settings/patch/TikTokSettingsPatch.kt +++ /dev/null @@ -1,98 +0,0 @@ -package app.revanced.patches.tiktok.misc.settings.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.tiktok.misc.integrations.patch.TikTokIntegrationsPatch -import app.revanced.patches.tiktok.misc.settings.annotations.TikTokSettingsCompatibility -import app.revanced.patches.tiktok.misc.settings.fingerprints.AdPersonalizationActivityFingerprint -import app.revanced.patches.tiktok.misc.settings.fingerprints.CopyRightSettingsStringFingerprint -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.instruction.formats.Instruction35c -import org.jf.dexlib2.iface.reference.MethodReference -import org.jf.dexlib2.iface.reference.StringReference - -@Patch -@DependsOn([TikTokIntegrationsPatch::class]) -@Name("tiktok-settings") -@Description("Add settings menu to TikTok.") -@TikTokSettingsCompatibility -@Version("0.0.1") -class TikTokSettingsPatch : BytecodePatch( - listOf( - AdPersonalizationActivityFingerprint, - CopyRightSettingsStringFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - //Replace string `Copyright Policy` to 'Revanced Settings` in TikTok settings. - val method1 = CopyRightSettingsStringFingerprint.result!!.mutableMethod - val implementation1 = method1.implementation!! - for ((index, instruction) in implementation1.instructions.withIndex()) { - if (instruction.opcode != Opcode.CONST_STRING) continue - val string = ((instruction as ReferenceInstruction).reference as StringReference).string - if (string != "copyright_policy") continue - var targetIndex = index - while (targetIndex >= 0) { - targetIndex-- - val invokeInstruction = implementation1.instructions[targetIndex] - if (invokeInstruction.opcode != Opcode.INVOKE_VIRTUAL) continue - val methodName = ((invokeInstruction as Instruction35c).reference as MethodReference).name - if (methodName != "getString") continue - val resultInstruction = implementation1.instructions[targetIndex + 1] - if (resultInstruction.opcode != Opcode.MOVE_RESULT_OBJECT) continue - val overrideRegister = (resultInstruction as OneRegisterInstruction).registerA - method1.replaceInstruction( - targetIndex + 1, - """ - const-string v$overrideRegister, "Revanced Settings" - """ - ) - break - } - //Change onClick to start settings activity. - val clickInstruction = implementation1.instructions[index - 1] - if (clickInstruction.opcode != Opcode.INVOKE_DIRECT) - return PatchResultError("Can not find click listener.") - val clickClass = ((clickInstruction as ReferenceInstruction).reference as MethodReference).definingClass - val mutableClickClass = context.findClass(clickClass)!!.mutableClass - val mutableOnClickMethod = mutableClickClass.methods.first { - it.name == "onClick" - } - mutableOnClickMethod.addInstructions( - 0, - """ - invoke-static {}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->startSettingsActivity()V - return-void - """ - ) - break - } - //Implement revanced settings screen in `AdPersonalizationActivity` - val method2 = AdPersonalizationActivityFingerprint.result!!.mutableMethod - for ((index, instruction) in method2.implementation!!.instructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_SUPER) continue - val thisRegister = (instruction as Instruction35c).registerC - method2.addInstructions( - index + 1, - """ - invoke-static {v$thisRegister}, Lapp/revanced/tiktok/settingsmenu/SettingsMenu;->initializeSettings(Lcom/bytedance/ies/ugc/aweme/commercialize/compliance/personalization/AdPersonalizationActivity;)V - return-void - """ - ) - break - } - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt deleted file mode 100644 index 0e39cb8..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/annotations/AudioAdsCompatibility.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.twitch.ad.audio.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("tv.twitch.android.app")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class AudioAdsCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt deleted file mode 100644 index 1cd867f..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/fingerprints/AudioAdsPresenterPlayFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.ad.audio.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.ad.audio.annotations.AudioAdsCompatibility - -@Name("audio-ads-presenter-play-fingerprint") -@AudioAdsCompatibility -@Version("0.0.1") -object AudioAdsPresenterPlayFingerprint : MethodFingerprint( - customFingerprint = { method -> - method.definingClass.endsWith("AudioAdsPlayerPresenter;") && method.name == "playAd" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt deleted file mode 100644 index ac680f5..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/audio/patch/AudioAdsPatch.kt +++ /dev/null @@ -1,31 +0,0 @@ -package app.revanced.patches.twitch.ad.audio.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.twitch.ad.audio.annotations.AudioAdsCompatibility -import app.revanced.patches.twitch.ad.audio.fingerprints.AudioAdsPresenterPlayFingerprint - -@Patch -@Name("block-audio-ads") -@Description("Blocks audio ads in streams and VODs.") -@AudioAdsCompatibility -@Version("0.0.1") -class AudioAdsPatch : BytecodePatch( - listOf(AudioAdsPresenterPlayFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - // Block playAds call - with(AudioAdsPresenterPlayFingerprint.result!!) { - mutableMethod.addInstruction(0, "return-void") - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt deleted file mode 100644 index 60c4d16..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/annotations/VideoAdsCompatibility.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.twitch.ad.video.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("tv.twitch.android.app")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class VideoAdsCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/AdsManagerFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/AdsManagerFingerprint.kt deleted file mode 100644 index 535da8b..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/AdsManagerFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.ad.video.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.ad.video.annotations.VideoAdsCompatibility - -@Name("ads-manager-play-fingerprint") -@VideoAdsCompatibility -@Version("0.0.1") -object AdsManagerFingerprint : MethodFingerprint( - customFingerprint = { method -> - method.definingClass.endsWith("AdsManagerImpl;") && method.name == "playAds" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt deleted file mode 100644 index 298abe4..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/CheckAdEligibilityLambdaFingerprint.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.twitch.ad.video.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.ad.video.annotations.VideoAdsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("check-ad-eligibility-fingerprint") -@VideoAdsCompatibility -@Version("0.0.1") -object CheckAdEligibilityLambdaFingerprint : MethodFingerprint( - "L", - AccessFlags.PRIVATE or AccessFlags.FINAL or AccessFlags.STATIC, - listOf("L", "L", "L"), - customFingerprint = { method -> - method.definingClass.endsWith("AdEligibilityFetcher;") && - method.name.contains("shouldRequestAd") - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt deleted file mode 100644 index af878a6..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/fingerprints/ContentConfigShowAdsFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.ad.video.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.ad.video.annotations.VideoAdsCompatibility - -@Name("content-config-show-ads-fingerprint") -@VideoAdsCompatibility -@Version("0.0.1") -object ContentConfigShowAdsFingerprint : MethodFingerprint( - customFingerprint = { method -> - method.definingClass.endsWith("ContentConfigData;") && method.name == "getShowAds" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt deleted file mode 100644 index e2ae844..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/ad/video/patch/VideoAdsPatch.kt +++ /dev/null @@ -1,60 +0,0 @@ -package app.revanced.patches.twitch.ad.video.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.twitch.ad.video.annotations.VideoAdsCompatibility -import app.revanced.patches.twitch.ad.video.fingerprints.AdsManagerFingerprint -import app.revanced.patches.twitch.ad.video.fingerprints.CheckAdEligibilityLambdaFingerprint -import app.revanced.patches.twitch.ad.video.fingerprints.ContentConfigShowAdsFingerprint - -@Patch -@Name("block-video-ads") -@Description("Blocks video ads in streams and VODs.") -@VideoAdsCompatibility -@Version("0.0.1") -class VideoAdsPatch : BytecodePatch( - listOf( - ContentConfigShowAdsFingerprint, - AdsManagerFingerprint, - CheckAdEligibilityLambdaFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - // Pretend our player is ineligible for all ads - with(CheckAdEligibilityLambdaFingerprint.result!!) { - mutableMethod.addInstructions( - 0, - """ - const/4 v0, 0 - invoke-static {v0}, Lio/reactivex/Single;->just(Ljava/lang/Object;)Lio/reactivex/Single; - move-result-object p0 - return-object p0 - """ - ) - } - - // Spoof showAds JSON field - with(ContentConfigShowAdsFingerprint.result!!) { - mutableMethod.addInstructions(0, """ - const/4 v0, 0 - return v0 - """ - ) - } - - // Block playAds call - with(AdsManagerFingerprint.result!!) { - mutableMethod.addInstruction(0, "return-void") - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt deleted file mode 100644 index c0c71be..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/annotations/ShowDeletedMessagesCompatibility.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.twitch.chat.antidelete.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("tv.twitch.android.app")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ShowDeletedMessagesCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt deleted file mode 100644 index c542722..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/DeletedMessageClickableSpanCtorFingerprint.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.twitch.chat.antidelete.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.chat.antidelete.annotations.ShowDeletedMessagesCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("deleted-msg-span-ctor-fingerprint") -@ShowDeletedMessagesCompatibility -@Version("0.0.1") -object DeletedMessageClickableSpanCtorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("DeletedMessageClickableSpan;") - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt deleted file mode 100644 index 33d8b21..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/fingerprints/SetHasModAccessFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.chat.antidelete.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.chat.antidelete.annotations.ShowDeletedMessagesCompatibility - -@Name("has-mod-access-fingerprint") -@ShowDeletedMessagesCompatibility -@Version("0.0.1") -object SetHasModAccessFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("DeletedMessageClickableSpan;") && methodDef.name == "setHasModAccess" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt b/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt deleted file mode 100644 index a6f3bfa..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/chat/antidelete/patch/ShowDeletedMessagesPatch.kt +++ /dev/null @@ -1,45 +0,0 @@ -package app.revanced.patches.twitch.chat.antidelete.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.* -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.twitch.chat.antidelete.annotations.ShowDeletedMessagesCompatibility -import app.revanced.patches.twitch.chat.antidelete.fingerprints.* -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction10x - -@Patch -@Name("show-deleted-messages") -@Description("Shows deleted chat messages behind a clickable spoiler.") -@ShowDeletedMessagesCompatibility -@Version("0.0.1") -class ShowDeletedMessagesPatch : BytecodePatch( - listOf( - SetHasModAccessFingerprint, - DeletedMessageClickableSpanCtorFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - // Force set hasModAccess member to true in constructor - with(DeletedMessageClickableSpanCtorFingerprint.result!!.mutableMethod) { - addInstructions( - implementation!!.instructions.lastIndex, /* place in front of return-void */ - """ - const/4 v0, 1 - iput-boolean v0, p0, $definingClass->hasModAccess:Z - """ - ) - } - - // Disable setHasModAccess setter - with(SetHasModAccessFingerprint.result!!.mutableMethod.implementation!!) { - addInstruction(0, BuilderInstruction10x(Opcode.RETURN_VOID)) - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt deleted file mode 100644 index 394b9e9..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/debug/annotations/DebugModeCompatibility.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.twitch.debug.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("tv.twitch.android.app")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DebugModeCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt deleted file mode 100644 index b0072e8..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsDebugConfigEnabledFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.debug.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.debug.annotations.DebugModeCompatibility - -@Name("is-debug-config-enabled-fingerprint") -@DebugModeCompatibility -@Version("0.0.1") -object IsDebugConfigEnabledFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "isDebugConfigEnabled" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt deleted file mode 100644 index b8e1085..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/IsOmVerificationEnabledFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.debug.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.debug.annotations.DebugModeCompatibility - -@Name("is-om-verification-enabled-fingerprint") -@DebugModeCompatibility -@Version("0.0.1") -object IsOmVerificationEnabledFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "isOmVerificationEnabled" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt deleted file mode 100644 index 6006fcb..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/debug/fingerprints/ShouldShowDebugOptionsFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.twitch.debug.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitch.debug.annotations.DebugModeCompatibility - -@Name("should-show-debug-options-fingerprint") -@DebugModeCompatibility -@Version("0.0.1") -object ShouldShowDebugOptionsFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("BuildConfigUtil;") && methodDef.name == "shouldShowDebugOptions" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt b/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt deleted file mode 100644 index 2829b97..0000000 --- a/src/main/kotlin/app/revanced/patches/twitch/debug/patch/DebugModePatch.kt +++ /dev/null @@ -1,49 +0,0 @@ -package app.revanced.patches.twitch.debug.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.twitch.debug.annotations.DebugModeCompatibility -import app.revanced.patches.twitch.debug.fingerprints.IsDebugConfigEnabledFingerprint -import app.revanced.patches.twitch.debug.fingerprints.IsOmVerificationEnabledFingerprint -import app.revanced.patches.twitch.debug.fingerprints.ShouldShowDebugOptionsFingerprint - -@Patch(false) -@Name("debug-mode") -@Description("Enables Twitch's internal debugging mode.") -@DebugModeCompatibility -@Version("0.0.1") -class DebugModePatch : BytecodePatch( - listOf( - IsDebugConfigEnabledFingerprint, - IsOmVerificationEnabledFingerprint, - ShouldShowDebugOptionsFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - listOf( - IsDebugConfigEnabledFingerprint, - IsOmVerificationEnabledFingerprint, - ShouldShowDebugOptionsFingerprint - ).forEach { - with(it.result!!) { - with(mutableMethod) { - addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - } - } - } - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/annotations/TimelineAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/annotations/TimelineAdsCompatibility.kt deleted file mode 100644 index 54ce876..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/annotations/TimelineAdsCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.twitter.ad.timeline.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.twitter.android")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class TimelineAdsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/fingerprints/TimelineTweetJsonParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/fingerprints/TimelineTweetJsonParserFingerprint.kt deleted file mode 100644 index b38cd77..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/fingerprints/TimelineTweetJsonParserFingerprint.kt +++ /dev/null @@ -1,24 +0,0 @@ -package app.revanced.patches.twitter.ad.timeline.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.twitter.ad.timeline.annotations.TimelineAdsCompatibility -import org.jf.dexlib2.Opcode - -@Name("timeline-tweet-json-parser-fingerprint") -@TimelineAdsCompatibility -@Version("0.0.1") -object TimelineTweetJsonParserFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.IPUT_OBJECT, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.IPUT_OBJECT, - Opcode.RETURN_VOID, - ), strings = listOf("tweetPromotedMetadata", "promotedMetadata", "hasModeratedReplies", "conversationAnnotation"), - customFingerprint = { methodDef -> methodDef.name == "parseField" } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/patch/TimelineAdsPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/patch/TimelineAdsPatch.kt deleted file mode 100644 index c8722e0..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/ad/timeline/patch/TimelineAdsPatch.kt +++ /dev/null @@ -1,77 +0,0 @@ -package app.revanced.patches.twitter.ad.timeline.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.twitter.ad.timeline.annotations.TimelineAdsCompatibility -import app.revanced.patches.twitter.ad.timeline.fingerprints.TimelineTweetJsonParserFingerprint -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.BuilderInstruction -import org.jf.dexlib2.builder.instruction.BuilderInstruction22c -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.StringReference - -@Patch -@Name("timeline-ads") -@Description("Removes ads from the Twitter timeline.") -@TimelineAdsCompatibility -@Version("0.0.1") -class TimelineAdsPatch : BytecodePatch( - listOf(TimelineTweetJsonParserFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - if (removePromotedAds()) - return PatchResultError("The instruction for the tweet id field could not be found") - - return PatchResultSuccess() - } - - private fun removePromotedAds(): Boolean { - val (parserFingerprintResult, parserMethod, instructions) = TimelineTweetJsonParserFingerprint.unwrap() - - // Anchor index - val tweetIdFieldInstructionIndex = instructions.indexOfFirst { instruction -> - if (instruction.opcode.ordinal != Opcode.CONST_STRING.ordinal) return@indexOfFirst false - if (((instruction as? ReferenceInstruction)?.reference as StringReference).string != "tweetSocialProof") return@indexOfFirst false - - // Use the above conditions as an anchor to find the index for the instruction with the field we need - return@indexOfFirst true - } - 2 // This is where the instruction with the field is located - - // Reference to the tweetId field for of the timeline tweet - val tweetIdFieldReference = - (parserMethod.instruction(tweetIdFieldInstructionIndex) as? BuilderInstruction22c)?.reference as? FieldReference - ?: return true - - // Set the tweetId field to null - // This will cause twitter to not show the promoted ads, because we set it to null, when the tweet is promoted - parserFingerprintResult.mutableMethod.addInstructions( - parserFingerprintResult.scanResult.patternScanResult!!.startIndex + 1, - """ - const/4 v2, 0x0 - iput-object v2, p0, Lcom/twitter/model/json/timeline/urt/JsonTimelineTweet;->${tweetIdFieldReference.name}:Ljava/lang/String; - """ - ) - return false - } - - private fun MethodFingerprint.unwrap(): Triple> { - val parserFingerprintResult = this.result!! - val parserMethod = parserFingerprintResult.mutableMethod - val instructions = parserMethod.implementation!!.instructions - - return Triple(parserFingerprintResult, parserMethod, instructions) - } -} diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt deleted file mode 100644 index 135276a..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/annotations/DynamicColorCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.twitter.misc.dynamiccolor.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.twitter.android")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DynamicColorCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt deleted file mode 100644 index 3ba3b56..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/dynamiccolor/patch/DynamicColorPatch.kt +++ /dev/null @@ -1,87 +0,0 @@ -package app.revanced.patches.twitter.misc.dynamiccolor.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.twitter.misc.dynamiccolor.annotations.DynamicColorCompatibility -import java.io.FileWriter -import java.nio.file.Files - -@Patch -@Name("dynamic-color") -@Description("Replaces the default Twitter Blue with the users Material You palette.") -@DynamicColorCompatibility -@Version("0.0.1") -class DynamicColorPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - val resDirectory = context["res"] - if (!resDirectory.isDirectory) return PatchResultError("The res folder can not be found.") - - val valuesV31Directory = resDirectory.resolve("values-v31") - if (!valuesV31Directory.isDirectory) Files.createDirectories(valuesV31Directory.toPath()) - - val valuesNightV31Directory = resDirectory.resolve("values-night-v31") - if (!valuesNightV31Directory.isDirectory) Files.createDirectories(valuesNightV31Directory.toPath()) - - listOf(valuesV31Directory, valuesNightV31Directory).forEach { it -> - val colorsXml = it.resolve("colors.xml") - - if(!colorsXml.exists()) { - FileWriter(colorsXml).use { - it.write("") - } - } - } - - context.xmlEditor["res/values-v31/colors.xml"].use { editor -> - val document = editor.file - - mapOf( - "ps__twitter_blue" to "@color/twitter_blue", - "ps__twitter_blue_pressed" to "@color/twitter_blue_fill_pressed", - "twitter_blue" to "@android:color/system_accent1_400", - "twitter_blue_fill_pressed" to "@android:color/system_accent1_300", - "twitter_blue_opacity_30" to "@android:color/system_accent1_100", - "twitter_blue_opacity_50" to "@android:color/system_accent1_200", - "twitter_blue_opacity_58" to "@android:color/system_accent1_300", - "deep_transparent_twitter_blue" to "@android:color/system_accent1_200", - "ic_launcher_background" to "#1DA1F2" - ).forEach { (k, v) -> - val colorElement = document.createElement("color") - - colorElement.setAttribute("name", k) - colorElement.textContent = v - - document.getElementsByTagName("resources").item(0).appendChild(colorElement) - } - } - - context.xmlEditor["res/values-night-v31/colors.xml"].use { editor -> - val document = editor.file - - mapOf( - "twitter_blue" to "@android:color/system_accent1_200", - "twitter_blue_fill_pressed" to "@android:color/system_accent1_300", - "twitter_blue_opacity_30" to "@android:color/system_accent1_50", - "twitter_blue_opacity_50" to "@android:color/system_accent1_100", - "twitter_blue_opacity_58" to "@android:color/system_accent1_200", - "deep_transparent_twitter_blue" to "@android:color/system_accent1_200" - ).forEach { (k, v) -> - val colorElement = document.createElement("color") - - colorElement.setAttribute("name", k) - colorElement.textContent = v - - document.getElementsByTagName("resources").item(0).appendChild(colorElement) - } - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/annotations/MonochromeIconCompatibility.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/annotations/MonochromeIconCompatibility.kt deleted file mode 100644 index 646ad2b..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/annotations/MonochromeIconCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.twitter.misc.monochrome.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.twitter.android")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MonochromeIconCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/patch/MonochromeIconPatch.kt b/src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/patch/MonochromeIconPatch.kt deleted file mode 100644 index 6e83ca5..0000000 --- a/src/main/kotlin/app/revanced/patches/twitter/misc/monochrome/patch/MonochromeIconPatch.kt +++ /dev/null @@ -1,55 +0,0 @@ -package app.revanced.patches.twitter.misc.monochrome.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.twitter.misc.monochrome.annotations.MonochromeIconCompatibility -import java.io.FileWriter -import java.nio.file.Files - -@Patch -@Name("monochrome-icon") -@Description("Adds a monochrome icon.") -@MonochromeIconCompatibility -@Version("0.0.1") -class MonochromeIconPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - val resDirectory = context["res"] - if (!resDirectory.isDirectory) return PatchResultError("The res folder can not be found.") - - val mipmapV33Directory = resDirectory.resolve("mipmap-anydpi-v33") - if (!mipmapV33Directory.isDirectory) Files.createDirectories(mipmapV33Directory.toPath()) - - FileWriter(mipmapV33Directory.resolve("ic_launcher_twitter.xml")).use { - it.write( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - "" - ) - } - - FileWriter(mipmapV33Directory.resolve("ic_launcher_twitter_round.xml")).use { - it.write( - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - "" - ) - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt deleted file mode 100644 index a87fa53..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/annotations/FirebaseGetCertPatchCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.warnwetter.misc.firebasegetcert.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("de.dwd.warnapp")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class FirebaseGetCertPatchCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertMessagingFingerprint.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertMessagingFingerprint.kt deleted file mode 100644 index b326c34..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertMessagingFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility - -@Name("messaging-app-certificate-fingerprint") -@FirebaseGetCertPatchCompatibility -@Version("0.0.1") -object GetMessagingCertFingerprint : MethodFingerprint( - "Ljava/lang/String;", - strings = listOf( - "ContentValues", - "Could not get fingerprint hash for package: ", - "No such package: " - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertRegistrationFingerprint.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertRegistrationFingerprint.kt deleted file mode 100644 index 80963b5..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/fingerprints/GetCertRegistrationFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility - -@Name("registration-app-certificate-fingerprint") -@FirebaseGetCertPatchCompatibility -@Version("0.0.1") -object GetReqistrationCertFingerprint : MethodFingerprint( - "Ljava/lang/String;", - strings = listOf( - "FirebaseRemoteConfig", - "Could not get fingerprint hash for package: ", - "No such package: " - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt deleted file mode 100644 index c7dd384..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/firebasegetcert/patch/FirebaseGetCertPatch.kt +++ /dev/null @@ -1,46 +0,0 @@ -package app.revanced.patches.warnwetter.misc.firebasegetcert.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patches.warnwetter.misc.firebasegetcert.annotations.FirebaseGetCertPatchCompatibility -import app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints.GetMessagingCertFingerprint -import app.revanced.patches.warnwetter.misc.firebasegetcert.fingerprints.GetReqistrationCertFingerprint - -@Name("spoof-cert-patch") -@Description("Spoofs the X-Android-Cert header.") -@FirebaseGetCertPatchCompatibility -@Version("0.0.1") -class FirebaseGetCertPatch : BytecodePatch( - listOf( - GetReqistrationCertFingerprint, - GetMessagingCertFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val spoofedInstruction = - """ - const-string v0, "0799DDF0414D3B3475E88743C91C0676793ED450" - return-object v0 - """ - - val registrationCertMethod = GetReqistrationCertFingerprint.result!!.mutableMethod - val messagingCertMethod = GetMessagingCertFingerprint.result!!.mutableMethod - - registrationCertMethod.addInstructions( - 0, - spoofedInstruction - ) - messagingCertMethod.addInstructions( - 0, - spoofedInstruction - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt deleted file mode 100644 index f4c2cc1..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/annotations/PromoCodeUnlockCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.warnwetter.misc.promocode.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("de.dwd.warnapp")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PromoCodeUnlockCompatibility diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt deleted file mode 100644 index d81a53d..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/fingerprints/PromoCodeUnlockFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.warnwetter.misc.promocode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.warnwetter.misc.promocode.annotations.PromoCodeUnlockCompatibility - -@Name("promo-code-unlock-fingerprint") -@PromoCodeUnlockCompatibility -@Version("0.0.1") -object PromoCodeUnlockFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("PromoTokenVerification;") && methodDef.name == "isValid" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt b/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt deleted file mode 100644 index 68ee1de..0000000 --- a/src/main/kotlin/app/revanced/patches/warnwetter/misc/promocode/patch/PromoCodeUnlockPatch.kt +++ /dev/null @@ -1,47 +0,0 @@ -package app.revanced.patches.warnwetter.misc.promocode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.warnwetter.misc.firebasegetcert.patch.FirebaseGetCertPatch -import app.revanced.patches.warnwetter.misc.promocode.annotations.PromoCodeUnlockCompatibility -import app.revanced.patches.warnwetter.misc.promocode.fingerprints.PromoCodeUnlockFingerprint - -@DependsOn( - [ - FirebaseGetCertPatch::class - ] -) -@Patch -@Name("promo-code-unlock") -@Description("Disables the validation of promo code. Any code will work to unlock all features.") -@PromoCodeUnlockCompatibility -@Version("0.0.1") -class PromoCodeUnlockPatch : BytecodePatch( - listOf( - PromoCodeUnlockFingerprint - ) -) { - - override fun execute(context: BytecodeContext): PatchResult { - val method = PromoCodeUnlockFingerprint.result!!.mutableMethod - method.addInstructions( - 0, - """ - const/4 v0, 0x1 - return v0 - """ - ) - - return PatchResultSuccess() - } - - -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt deleted file mode 100644 index 19995e9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/annotation/GeneralAdsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.ad.general.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class GeneralAdsCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/bytecode/patch/GeneralBytecodeAdsPatch.kt deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/general/patch/GeneralAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/general/patch/GeneralAdsPatch.kt deleted file mode 100644 index fb8d02e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/general/patch/GeneralAdsPatch.kt +++ /dev/null @@ -1,179 +0,0 @@ -package app.revanced.patches.youtube.ad.general.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.ad.general.annotation.GeneralAdsCompatibility -import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn(dependencies = [FixLocaleConfigErrorPatch::class, LithoFilterPatch::class, SettingsPatch::class]) -@Name("general-ads") -@Description("Removes general ads.") -@GeneralAdsCompatibility -@Version("0.0.1") -class GeneralAdsPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.ADS.addPreferences( - SwitchPreference( - "revanced_home_ads_removal", - StringResource("revanced_home_ads_removal_title", "Remove home ads"), - true, - StringResource("revanced_home_ads_removal_summary_on", "Home ads are hidden"), - StringResource("revanced_home_ads_removal_summary_off", "Home ads are shown") - ), - SwitchPreference( - "revanced_adremover_ad_removal", - StringResource("revanced_adremover_ad_removal_enabled_title", "Remove general ads"), - true, - StringResource("revanced_adremover_ad_removal_enabled_summary_on", "General ads are hidden"), - StringResource("revanced_adremover_ad_removal_enabled_summary_off", "General ads are shown") - ), - SwitchPreference( - "revanced_adremover_merchandise", - StringResource("revanced_adremover_merchandise_enabled_title", "Remove merchandise banners"), - true, - StringResource("revanced_adremover_merchandise_enabled_summary_on", "Merchandise banners are hidden"), - StringResource("revanced_adremover_merchandise_enabled_summary_off", "Merchandise banners are shown") - ), - SwitchPreference( - "revanced_adremover_community_posts_removal", - StringResource("revanced_adremover_community_posts_enabled_title", "Remove community posts"), - false, - StringResource("revanced_adremover_community_posts_enabled_summary_on", "Community posts are hidden"), - StringResource("revanced_adremover_community_posts_enabled_summary_off", "Community posts are shown") - ), - SwitchPreference( - "revanced_adremover_compact_banner_removal", - StringResource("revanced_adremover_compact_banner_enabled_title", "Remove compact banners"), - true, - StringResource("revanced_adremover_compact_banner_enabled_summary_on", "Compact banners are hidden"), - StringResource("revanced_adremover_compact_banner_enabled_summary_off", "Compact banners are shown") - ), - SwitchPreference( - "revanced_adremover_movie", - StringResource("revanced_adremover_movie_enabled_title", "Remove movies section"), - true, - StringResource("revanced_adremover_movie_enabled_summary_on", "Movies section is hidden"), - StringResource("revanced_adremover_movie_enabled_summary_off", "Movies section is shown") - ), - SwitchPreference( - "revanced_adremover_feed_survey", - StringResource("revanced_adremover_feed_survey_enabled_title", "Remove feed surveys"), - true, - StringResource("revanced_adremover_feed_survey_enabled_summary_on", "Feed surveys are hidden"), - StringResource("revanced_adremover_feed_survey_enabled_summary_off", "Feed surveys are shown") - ), - SwitchPreference( - "revanced_adremover_shorts", - StringResource("revanced_adremover_shorts_enabled_title", "Remove shorts"), - true, - StringResource("revanced_adremover_shorts_enabled_summary_on", "Shorts are hidden"), - StringResource("revanced_adremover_shorts_enabled_summary_off", "Shorts are shown") - ), - SwitchPreference( - "revanced_adremover_community_guidelines", - StringResource("revanced_adremover_community_guidelines_enabled_title", "Remove community guidelines"), - true, - StringResource( - "revanced_adremover_community_guidelines_enabled_summary_on", - "Community guidelines are hidden" - ), - StringResource( - "revanced_adremover_community_guidelines_enabled_summary_off", - "Community guidelines are shown" - ) - ), - SwitchPreference( - "revanced_adremover_emergency_box_removal", - StringResource("revanced_adremover_emergency_box_enabled_title", "Remove emergency boxes"), - true, - StringResource("revanced_adremover_emergency_box_enabled_summary_on", "Emergency boxes are hidden"), - StringResource("revanced_adremover_emergency_box_enabled_summary_off", "Emergency boxes are shown") - ), - SwitchPreference( - "revanced_adremover_info_panel", - StringResource("revanced_adremover_info_panel_enabled_title", "Remove info panels"), - true, - StringResource("revanced_adremover_info_panel_enabled_summary_on", "Info panels are hidden"), - StringResource("revanced_adremover_info_panel_enabled_summary_off", "Info panels are shown") - ), - SwitchPreference( - "revanced_adremover_medical_panel", - StringResource("revanced_adremover_medical_panel_enabled_title", "Remove medical panels"), - true, - StringResource("revanced_adremover_medical_panel_enabled_summary_on", "Medical panels are hidden"), - StringResource("revanced_adremover_medical_panel_enabled_summary_off", "Medical panels are shown") - ), - SwitchPreference( - "revanced_adremover_paid_content", - StringResource("revanced_adremover_paid_content_enabled_title", "Remove paid content"), - true, - StringResource("revanced_adremover_paid_content_enabled_summary_on", "Paid content is hidden"), - StringResource("revanced_adremover_paid_content_enabled_summary_off", "Paid content is shown") - ), - SwitchPreference( - "revanced_adremover_hide_suggestions", - StringResource("revanced_adremover_hide_suggestions_enabled_title", "Hide suggestions"), - true, - StringResource("revanced_adremover_hide_suggestions_enabled_summary_on", "Suggestions are hidden"), - StringResource("revanced_adremover_hide_suggestions_enabled_summary_off", "Suggestions are shown") - ), - SwitchPreference( - "revanced_adremover_hide_latest_posts", - StringResource("revanced_adremover_hide_latest_posts_enabled_title", "Hide latest posts"), - true, - StringResource("revanced_adremover_hide_latest_posts_enabled_summary_on", "Latest posts are hidden"), - StringResource("revanced_adremover_hide_latest_posts_enabled_summary_off", "Latest posts are shown") - ), - SwitchPreference( - "revanced_adremover_hide_channel_guidelines", - StringResource("revanced_adremover_hide_channel_guidelines_enabled_title", "Hide channel guidelines"), - true, - StringResource( - "revanced_adremover_hide_channel_guidelines_enabled_summary_on", - "Channel guidelines are hidden" - ), - StringResource( - "revanced_adremover_hide_channel_guidelines_enabled_summary_off", - "Channel guidelines are shown" - ) - ), - SwitchPreference( - "revanced_adremover_self_sponsor", - StringResource("revanced_adremover_self_sponsor_enabled_title", "Hide self sponsored cards"), - true, - StringResource("revanced_adremover_self_sponsor_enabled_summary_on", "Self sponsored cards are hidden"), - StringResource("revanced_adremover_self_sponsor_enabled_summary_off", "Self sponsored cards are shown") - ), - SwitchPreference( - "revanced_adremover_chapter_teaser", - StringResource( - "revanced_adremover_chapter_teaser_enabled_title", - "Hide chapter teaser under videos" - ), - true, - StringResource( - "revanced_adremover_chapter_teaser_enabled_summary_on", - "Chapter teasers are hidden" - ), - StringResource( - "revanced_adremover_chapter_teaser_enabled_summary_off", - "Chapter teasers are shown" - ) - ) - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt deleted file mode 100644 index a5c7253..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/annotations/VideoAdsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.ad.video.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class VideoAdsCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/fingerprints/LoadVideoAdsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/fingerprints/LoadVideoAdsFingerprint.kt deleted file mode 100644 index d408393..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/fingerprints/LoadVideoAdsFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.ad.video.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility - -@Name("load-ads-fingerprint") -@VideoAdsCompatibility -@Version("0.0.1") -object LoadVideoAdsFingerprint : MethodFingerprint( - strings = listOf( - "TriggerBundle doesn't have the required metadata specified by the trigger ", - "Tried to enter slot with no assigned slotAdapter", - "Trying to enter a slot when a slot of same type and physical position is already active. Its status: ", - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt deleted file mode 100644 index 21ee64c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/ad/video/patch/VideoAdsPatch.kt +++ /dev/null @@ -1,58 +0,0 @@ -package app.revanced.patches.youtube.ad.video.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.ad.video.annotations.VideoAdsCompatibility -import app.revanced.patches.youtube.ad.video.fingerprints.LoadVideoAdsFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.playback.fix.patch.FixPlaybackPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class, FixPlaybackPatch::class]) -@Name("video-ads") -@Description("Removes ads in the video player.") -@VideoAdsCompatibility -@Version("0.0.1") -class VideoAdsPatch : BytecodePatch( - listOf( - LoadVideoAdsFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.ADS.addPreferences( - SwitchPreference( - "revanced_video_ads_removal", - StringResource("revanced_video_ads_removal_title", "Hide video ads"), - true, - StringResource("revanced_video_ads_removal_summary_on", "Video ads are hidden"), - StringResource("revanced_video_ads_removal_summary_off", "Video ads are shown") - ) - ) - - val loadVideoAdsFingerprintMethod = LoadVideoAdsFingerprint.result!!.mutableMethod - - loadVideoAdsFingerprintMethod.addInstructions( - 0, """ - invoke-static { }, Lapp/revanced/integrations/patches/VideoAdsPatch;->shouldShowAds()Z - move-result v0 - if-nez v0, :show_video_ads - return-void - """, listOf(ExternalLabel("show_video_ads", loadVideoAdsFingerprintMethod.instruction(0))) - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt deleted file mode 100644 index a5a53d1..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/annotation/DownloadsCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.interaction.downloads.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DownloadsCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt deleted file mode 100644 index c5e6ba0..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/bytecode/patch/DownloadsBytecodePatch.kt +++ /dev/null @@ -1,52 +0,0 @@ -package app.revanced.patches.youtube.interaction.downloads.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility -import app.revanced.patches.youtube.interaction.downloads.resource.patch.DownloadsResourcePatch -import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch -import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch - -@Patch -@Name("downloads") -@DependsOn([DownloadsResourcePatch::class, PlayerControlsBytecodePatch::class, VideoIdPatch::class]) -@Description("Enables downloading music and videos from YouTube.") -@DownloadsCompatibility -@Version("0.0.1") -class DownloadsBytecodePatch : BytecodePatch() { - override fun execute(context: BytecodeContext): PatchResult { - val integrationsPackage = "app/revanced/integrations" - val classDescriptor = "L$integrationsPackage/videoplayer/DownloadButton;" - - /* - initialize the control - */ - - val initializeDownloadsDescriptor = "$classDescriptor->initializeDownloadButton(Ljava/lang/Object;)V" - PlayerControlsBytecodePatch.initializeControl(initializeDownloadsDescriptor) - - /* - add code to change the visibility of the control - */ - - val changeVisibilityDescriptor = "$classDescriptor->changeVisibility(Z)V" - PlayerControlsBytecodePatch.injectVisibilityCheckCall(changeVisibilityDescriptor) - - /* - add code to change to update the video id - */ - - val setVideoIdDescriptor = - "L$integrationsPackage/patches/downloads/DownloadsPatch;->setVideoId(Ljava/lang/String;)V" - VideoIdPatch.injectCall(setVideoIdDescriptor) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt deleted file mode 100644 index 9c59df0..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/downloads/resource/patch/DownloadsResourcePatch.kt +++ /dev/null @@ -1,72 +0,0 @@ -package app.revanced.patches.youtube.interaction.downloads.resource.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.interaction.downloads.annotation.DownloadsCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.playercontrols.resource.patch.BottomControlsResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.* -import app.revanced.util.resources.ResourceUtils -import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings -import app.revanced.util.resources.ResourceUtils.copyResources - -@Name("downloads-resource-patch") -@DependsOn([BottomControlsResourcePatch::class, FixLocaleConfigErrorPatch::class, SettingsPatch::class]) -@Description("Makes necessary changes to resources for the download button.") -@DownloadsCompatibility -@Version("0.0.1") -class DownloadsResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences( - PreferenceScreen( - "revanced_downloads", - StringResource("revanced_downloads_title", "Download settings"), - listOf( - SwitchPreference( - "revanced_downloads", - StringResource("revanced_downloads_enabled_title", "Show download button"), - true, - StringResource("revanced_downloads_enabled_summary_on", "Download button is visible"), - StringResource("revanced_downloads_enabled_summary_off", "Download button is hidden") - ), - TextPreference( - "revanced_downloads_package_name", - StringResource("revanced_downloads_package_name_title", "Downloader package name"), - InputType.STRING, - "org.schabi.newpipe" /* NewPipe */, - StringResource("revanced_downloads_package_name_summary", "Package name of the downloader app such as NewPipe\\'s or PowerTube\\'s") - ) - ), - StringResource("revanced_downloads_summary", "Settings related to downloads") - ) - ) - - - /* - * Copy strings - */ - - context.mergeStrings("downloads/host/values/strings.xml") - - /* - * Copy resources - */ - - context.copyResources("downloads", ResourceUtils.ResourceGroup("drawable", "revanced_yt_download_button.xml")) - - /* - * Add download button node - */ - - BottomControlsResourcePatch.addControls("downloads/host/layout/${BottomControlsResourcePatch.TARGET_RESOURCE_NAME}") - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt deleted file mode 100644 index 277c9ee..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/annotation/SeekbarTappingCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.interaction.seekbar.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SeekbarTappingCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt deleted file mode 100644 index 42117f8..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingFingerprint.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.revanced.patches.youtube.interaction.seekbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("enable-seekbar-tapping-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@SeekbarTappingCompatibility -@Version("0.0.1") -object SeekbarTappingFingerprint : MethodFingerprint( - "Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.IGET, - Opcode.IGET_OBJECT, - Opcode.IGET, - Opcode.DIV_INT_2ADDR, - Opcode.ADD_INT, - Opcode.SUB_INT_2ADDR, - Opcode.INT_TO_FLOAT, - Opcode.CMPG_FLOAT, - Opcode.IF_GTZ, - Opcode.INT_TO_FLOAT, - Opcode.CMPG_FLOAT, - Opcode.IF_GTZ, - Opcode.CONST_4, - Opcode.INVOKE_INTERFACE, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt deleted file mode 100644 index a0c4a23..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/fingerprints/SeekbarTappingParentFingerprint.kt +++ /dev/null @@ -1,49 +0,0 @@ -package app.revanced.patches.youtube.interaction.seekbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("enable-seekbar-tapping-parent-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@SeekbarTappingCompatibility -@Version("0.0.1") -object SeekbarTappingParentFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.NEW_ARRAY, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.APUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_4, - Opcode.APUT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.RETURN_OBJECT - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt deleted file mode 100644 index 0fb295a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/seekbar/patch/EnableSeekbarTappingPatch.kt +++ /dev/null @@ -1,110 +0,0 @@ -package app.revanced.patches.youtube.interaction.seekbar.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.interaction.seekbar.annotation.SeekbarTappingCompatibility -import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingFingerprint -import app.revanced.patches.youtube.interaction.seekbar.fingerprints.SeekbarTappingParentFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21t -import org.jf.dexlib2.iface.Method -import org.jf.dexlib2.iface.instruction.formats.Instruction11n -import org.jf.dexlib2.iface.instruction.formats.Instruction35c - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("seekbar-tapping") -@Description("Enables tap-to-seek on the seekbar of the video player.") -@SeekbarTappingCompatibility -@Version("0.0.1") -class EnableSeekbarTappingPatch : BytecodePatch( - listOf( - SeekbarTappingParentFingerprint, SeekbarTappingFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences( - SwitchPreference( - "revanced_enable_tap_seeking", - StringResource("revanced_seekbar_tapping_enabled_title", "Enable seekbar tapping"), - true, - StringResource("revanced_seekbar_tapping_summary_on", "Seekbar tapping is enabled"), - StringResource("revanced_seekbar_tapping_summary_off", "Seekbar tapping is disabled") - ) - ) - - var result = SeekbarTappingParentFingerprint.result!! - - val tapSeekMethods = mutableMapOf() - - // find the methods which tap the seekbar - for (it in result.classDef.methods) { - if (it.implementation == null) continue - - val instructions = it.implementation!!.instructions - // here we make sure we actually find the method because it has more than 7 instructions - if (instructions.count() < 7) continue - - // we know that the 7th instruction has the opcode CONST_4 - val instruction = instructions.elementAt(6) - if (instruction.opcode != Opcode.CONST_4) continue - - // the literal for this instruction has to be either 1 or 2 - val literal = (instruction as Instruction11n).narrowLiteral - - // method founds - if (literal == 1) tapSeekMethods["P"] = it - if (literal == 2) tapSeekMethods["O"] = it - } - - // replace map because we don't need the upper one anymore - result = SeekbarTappingFingerprint.result!! - - val implementation = result.mutableMethod.implementation!! - - // if tap-seeking is enabled, do not invoke the two methods below - val pMethod = tapSeekMethods["P"]!! - val oMethod = tapSeekMethods["O"]!! - - val insertIndex = result.scanResult.patternScanResult!!.endIndex + 1 - - // get the required register - val instruction = implementation.instructions[insertIndex - 1] - if (instruction.opcode != Opcode.INVOKE_VIRTUAL) return PatchResultError("Could not find the correct register") - val register = (instruction as Instruction35c).registerC - - val elseLabel = implementation.newLabelForIndex(insertIndex) - // the instructions are written in reverse order. - result.mutableMethod.addInstructions( - insertIndex, """ - invoke-virtual { v$register, v2 }, ${oMethod.definingClass}->${oMethod.name}(I)V - invoke-virtual { v$register, v2 }, ${pMethod.definingClass}->${pMethod.name}(I)V - """ - ) - - // if tap-seeking is disabled, do not invoke the two methods above by jumping to the else label - implementation.addInstruction( - insertIndex, BuilderInstruction21t(Opcode.IF_EQZ, 0, elseLabel) - ) - result.mutableMethod.addInstructions( - insertIndex, """ - invoke-static { }, Lapp/revanced/integrations/patches/SeekbarTappingPatch;->isTapSeekingEnabled()Z - move-result v0 - """ - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt deleted file mode 100644 index c50b2f5..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/annotation/SwipeControlsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.interaction.swipecontrols.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SwipeControlsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt deleted file mode 100644 index 3a03066..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/fingerprints/SwipeControlsHostActivityFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.interaction.swipecontrols.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility - -@Name("swipe-controls-host-activity-fingerprint") - -@SwipeControlsCompatibility -@Version("0.0.1") -object SwipeControlsHostActivityFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass == "Lapp/revanced/integrations/swipecontrols/SwipeControlsHostActivity;" && methodDef.name == "" - } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt deleted file mode 100644 index 60f9aa7..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/bytecode/SwipeControlsBytecodePatch.kt +++ /dev/null @@ -1,68 +0,0 @@ -package app.revanced.patches.youtube.interaction.swipecontrols.patch.bytecode - -import app.revanced.extensions.transformMethods -import app.revanced.extensions.traverseClassHierarchy -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility -import app.revanced.patches.youtube.interaction.swipecontrols.fingerprints.SwipeControlsHostActivityFingerprint -import app.revanced.shared.fingerprints.WatchWhileActivityFingerprint -import app.revanced.patches.youtube.interaction.swipecontrols.patch.resource.SwipeControlsResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.immutable.ImmutableMethod - -@Patch -@Name("swipe-controls") -@Description("Adds volume and brightness swipe controls.") -@SwipeControlsCompatibility -@Version("0.0.3") -@DependsOn( - [ - IntegrationsPatch::class, - PlayerTypeHookPatch::class, - SwipeControlsResourcePatch::class - ] -) -class SwipeControlsBytecodePatch : BytecodePatch( - listOf( - WatchWhileActivityFingerprint, - SwipeControlsHostActivityFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val wrapperClass = SwipeControlsHostActivityFingerprint.result!!.mutableClass - val targetClass = WatchWhileActivityFingerprint.result!!.mutableClass - - // inject the wrapper class from integrations into the class hierarchy of WatchWhileActivity - wrapperClass.setSuperClass(targetClass.superclass) - targetClass.setSuperClass(wrapperClass.type) - - // ensure all classes and methods in the hierarchy are non-final, so we can override them in integrations - context.traverseClassHierarchy(targetClass) { - accessFlags = accessFlags and AccessFlags.FINAL.value.inv() - transformMethods { - ImmutableMethod( - definingClass, - name, - parameters, - returnType, - accessFlags and AccessFlags.FINAL.value.inv(), - annotations, - hiddenApiRestrictions, - implementation - ).toMutable() - } - } - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt deleted file mode 100644 index 6653452..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/interaction/swipecontrols/patch/resource/SwipeControlsResourcePatch.kt +++ /dev/null @@ -1,107 +0,0 @@ -package app.revanced.patches.youtube.interaction.swipecontrols.patch.resource - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.* -import app.revanced.util.resources.ResourceUtils -import app.revanced.util.resources.ResourceUtils.copyResources - -@Name("swipe-controls-resource-patch") -@DependsOn([SettingsPatch::class]) -@SwipeControlsCompatibility -@Version("0.0.1") -class SwipeControlsResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.INTERACTIONS.addPreferences( - PreferenceScreen( - "revanced_swipe_controls", StringResource("revanced_swipe_controls_title", "Swipe controls"), listOf( - SwitchPreference( - "revanced_enable_swipe_brightness", - StringResource("revanced_swipe_brightness_enabled_title", "Enable brightness gesture"), - true, - StringResource("revanced_swipe_brightness_summary_on", "Brightness swipe is enabled"), - StringResource("revanced_swipe_brightness_summary_off", "Brightness swipe is disabled") - ), - SwitchPreference( - "revanced_enable_swipe_volume", - StringResource("revanced_swipe_volume_enabled_title", "Enable volume gesture"), - true, - StringResource("revanced_swipe_volume_summary_on", "Volume swipe is enabled"), - StringResource("revanced_swipe_volume_summary_off", "Volume swipe is disabled") - ), - SwitchPreference( - "revanced_enable_press_to_swipe", - StringResource("revanced_press_to_swipe_enabled_title", "Enable press-to-swipe gesture"), - false, - StringResource("revanced_press_to_swipe_summary_on", "Press-to-swipe is enabled"), - StringResource("revanced_press_to_swipe_summary_off", "Press-to-swipe is disabled") - ), - SwitchPreference( - "revanced_enable_swipe_haptic_feedback", - StringResource("revanced_swipe_haptic_feedback_enabled_title", "Enable haptic feedback"), - true, - StringResource("revanced_swipe_haptic_feedback_summary_on", "Haptic feedback is enabled"), - StringResource("revanced_swipe_haptic_feedback_summary_off", "Haptic feedback is disabled") - ), - TextPreference( - "revanced_swipe_overlay_timeout", - StringResource("revanced_swipe_overlay_timeout_title", "Swipe overlay timeout"), - InputType.NUMBER, - "500", - StringResource( - "revanced_swipe_overlay_timeout_summary", - "The amount of milliseconds the overlay is visible" - ) - ), - TextPreference( - "revanced_swipe_overlay_text_size", - StringResource("revanced_swipe_overlay_text_size_title", "Swipe overlay text size"), - InputType.NUMBER, - "22", - StringResource("revanced_swipe_overlay_text_size_summary", "The text size for swipe overlay") - ), - TextPreference( - "revanced_swipe_overlay_background_alpha", - StringResource("revanced_swipe_overlay_background_alpha_title", "Swipe background visibility"), - InputType.NUMBER, - "127", - StringResource( - "revanced_swipe_overlay_background_alpha_summary", - "The visibility of swipe overlay background" - ) - ), - TextPreference( - "revanced_swipe_magnitude_threshold", - StringResource("revanced_swipe_magnitude_threshold_title", "Swipe magnitude threshold"), - InputType.NUMBER, - "30", - StringResource( - "revanced_swipe_magnitude_threshold_summary", - "The amount of threshold for swipe to occur" - ) - ) - ), - StringResource("revanced_swipe_controls_summary","Control volume and brightness") - ) - ) - - context.copyResources( - "swipecontrols", - ResourceUtils.ResourceGroup( - "drawable", - "ic_sc_brightness_auto.xml", - "ic_sc_brightness_manual.xml", - "ic_sc_volume_mute.xml", - "ic_sc_volume_normal.xml" - ) - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt deleted file mode 100644 index 9b1b17c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/annotations/AutoCaptionsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.autocaptions.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class AutoCaptionsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt deleted file mode 100644 index 2653026..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/StartVideoInformerFingerprint.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.youtube.layout.autocaptions.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.autocaptions.annotations.AutoCaptionsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("start-video-informer-fingerprint") -@FuzzyPatternScanMethod(3) -@AutoCaptionsCompatibility -@Version("0.0.1") -object StartVideoInformerFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L", "L", "L"), listOf( - Opcode.INVOKE_STATIC, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_INTERFACE, - Opcode.IF_EQZ, - Opcode.CONST_STRING, - Opcode.INVOKE_INTERFACE, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.CONST_4, - Opcode.IF_EQ, - Opcode.GOTO, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleButtonControllerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleButtonControllerFingerprint.kt deleted file mode 100644 index 49923e3..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleButtonControllerFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.youtube.layout.autocaptions.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.autocaptions.annotations.AutoCaptionsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("subtitle-button-controller-fingerprint") -@AutoCaptionsCompatibility -@Version("0.0.1") -object SubtitleButtonControllerFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.RETURN_VOID, - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleTrackFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleTrackFingerprint.kt deleted file mode 100644 index 9a27b1d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/fingerprints/SubtitleTrackFingerprint.kt +++ /dev/null @@ -1,24 +0,0 @@ -package app.revanced.patches.youtube.layout.autocaptions.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.autocaptions.annotations.AutoCaptionsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("subtitle-track-fingerprint") -@AutoCaptionsCompatibility -@Version("0.0.1") -object SubtitleTrackFingerprint : MethodFingerprint( - "Z", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.CONST_STRING, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.RETURN, - ), - strings = listOf("DISABLE_CAPTIONS_OPTION") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt deleted file mode 100644 index 9990da9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autocaptions/patch/AutoCaptionsPatch.kt +++ /dev/null @@ -1,80 +0,0 @@ -package app.revanced.patches.youtube.layout.autocaptions.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.autocaptions.annotations.AutoCaptionsCompatibility -import app.revanced.patches.youtube.layout.autocaptions.fingerprints.StartVideoInformerFingerprint -import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleButtonControllerFingerprint -import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleTrackFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("disable-auto-captions") -@Description("Disable forced captions from being automatically enabled.") -@AutoCaptionsCompatibility -@Version("0.0.1") -class AutoCaptionsPatch : BytecodePatch( - listOf( - StartVideoInformerFingerprint, SubtitleButtonControllerFingerprint, SubtitleTrackFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_autocaptions_enabled", - StringResource("revanced_autocaptions_enabled_title", "Disable auto-captions"), - false, - StringResource("revanced_autocaptions_summary_on", "Auto-captions are disabled"), - StringResource("revanced_autocaptions_summary_off", "Auto-captions are enabled") - ) - ) - - val startVideoInformerMethod = StartVideoInformerFingerprint.result!!.mutableMethod - - startVideoInformerMethod.addInstructions( - 0, """ - const/4 v0, 0x0 - sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z - """ - ) - - val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod - - subtitleButtonControllerMethod.addInstructions( - 0, """ - const/4 v0, 0x1 - sput-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z - """ - ) - - val subtitleTrackMethod = SubtitleTrackFingerprint.result!!.mutableMethod - - subtitleTrackMethod.addInstructions( - 0, """ - invoke-static {}, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->autoCaptionsEnabled()Z - move-result v0 - if-eqz v0, :auto_captions_enabled - sget-boolean v0, Lapp/revanced/integrations/patches/DisableAutoCaptionsPatch;->captionsButtonDisabled:Z - if-nez v0, :auto_captions_enabled - const/4 v0, 0x1 - return v0 - :auto_captions_enabled - nop - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt deleted file mode 100644 index 1b689cd..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/annotations/AutoplayButtonCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.autoplaybutton.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class AutoplayButtonCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutoNavInformerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutoNavInformerFingerprint.kt deleted file mode 100644 index f113292..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/AutoNavInformerFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.youtube.layout.autoplaybutton.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("autonav-informer-fingerprint") -@AutoplayButtonCompatibility -@Version("0.0.1") -object AutoNavInformerFingerprint : MethodFingerprint( - "Z", - AccessFlags.PUBLIC or AccessFlags.FINAL, - opcodes = listOf( - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - ), - customFingerprint = { it.definingClass.endsWith("WillAutonavInformer;") } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt deleted file mode 100644 index 4b96c87..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/fingerprints/LayoutConstructorFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.layout.autoplaybutton.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility - -@Name("layout-constructor-fingerprint") -@AutoplayButtonCompatibility -@Version("0.0.1") -object LayoutConstructorFingerprint : MethodFingerprint( - strings = listOf("1.0x"), - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("YouTubeControlsOverlay;") - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/HideAutoplayButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/HideAutoplayButtonPatch.kt deleted file mode 100644 index b3860c2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/autoplaybutton/patch/HideAutoplayButtonPatch.kt +++ /dev/null @@ -1,92 +0,0 @@ -package app.revanced.patches.youtube.layout.autoplaybutton.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.layout.autoplaybutton.annotations.AutoplayButtonCompatibility -import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.AutoNavInformerFingerprint -import app.revanced.patches.youtube.layout.autoplaybutton.fingerprints.LayoutConstructorFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.Instruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction -import org.jf.dexlib2.iface.reference.MethodReference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Name("hide-autoplay-button") -@Description("Hides the autoplay button in the video player.") -@AutoplayButtonCompatibility -@Version("0.0.1") -class HideAutoplayButtonPatch : BytecodePatch( - listOf( - LayoutConstructorFingerprint, AutoNavInformerFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_autoplay_button_enabled", - StringResource("revanced_autoplay_button_enabled_title", "Show autoplay button"), - false, - StringResource("revanced_autoplay_button_summary_on", "Autoplay button is shown"), - StringResource("revanced_autoplay_button_summary_off", "Autoplay button is hidden") - ) - ) - - val autoNavInformerMethod = AutoNavInformerFingerprint.result!!.mutableMethod - - val layoutGenMethodResult = LayoutConstructorFingerprint.result!! - val layoutGenMethod = layoutGenMethodResult.mutableMethod - val layoutGenMethodInstructions = layoutGenMethod.implementation!!.instructions - - // resolve the offsets such as ... - val autoNavPreviewStubId = ResourceMappingResourcePatch.resourceMappings.single { - it.name == "autonav_preview_stub" - }.id - // where to insert the branch instructions and ... - val insertIndex = layoutGenMethodInstructions.indexOfFirst { - (it as? WideLiteralInstruction)?.wideLiteral == autoNavPreviewStubId - } - // where to branch away - val branchIndex = layoutGenMethodInstructions.subList(insertIndex + 1, layoutGenMethodInstructions.size - 1).indexOfFirst { - ((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "addOnLayoutChangeListener" - } + 2 - - val jumpInstruction = layoutGenMethodInstructions[insertIndex + branchIndex] as Instruction - layoutGenMethod.addInstructions( - insertIndex, """ - invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z - move-result v11 - if-eqz v11, :hidden - """, listOf(ExternalLabel("hidden", jumpInstruction)) - ) - - //force disable autoplay since it's hard to do without the button - autoNavInformerMethod.addInstructions( - 0, """ - invoke-static {}, Lapp/revanced/integrations/patches/HideAutoplayButtonPatch;->isButtonShown()Z - move-result v0 - if-nez v0, :hidden - const/4 v0, 0x0 - return v0 - :hidden - nop - """ - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt deleted file mode 100644 index 96b1d50..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/annotations/PremiumHeadingCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.branding.header.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PremiumHeadingCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt deleted file mode 100644 index 83eca46..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/header/patch/PremiumHeadingPatch.kt +++ /dev/null @@ -1,51 +0,0 @@ -package app.revanced.patches.youtube.layout.branding.header.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.branding.header.annotations.PremiumHeadingCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import java.nio.file.Files -import java.nio.file.StandardCopyOption -import kotlin.io.path.exists - -@Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) -@Name("premium-heading") -@Description("Shows premium branding on the home screen.") -@PremiumHeadingCompatibility -@Version("0.0.1") -class PremiumHeadingPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - val resDirectory = context["res"] - if (!resDirectory.isDirectory) return PatchResultError("The res folder can not be found.") - - val (original, replacement) = "yt_premium_wordmark_header" to "yt_wordmark_header" - val modes = arrayOf("light", "dark") - - arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi").forEach { size -> - val headingDirectory = resDirectory.resolve("drawable-$size") - modes.forEach { mode -> - val fromPath = headingDirectory.resolve("${original}_$mode.png").toPath() - val toPath = headingDirectory.resolve("${replacement}_$mode.png").toPath() - - if (!fromPath.exists()) - return PatchResultError("The file $fromPath does not exist in the resources. Therefore, this patch can not succeed.") - Files.copy( - fromPath, - toPath, - StandardCopyOption.REPLACE_EXISTING - ) - } - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt deleted file mode 100644 index a0ffc71..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/annotations/CustomBrandingCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.branding.icon.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CustomBrandingCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt deleted file mode 100644 index f373fd6..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/branding/icon/patch/CustomBrandingPatch.kt +++ /dev/null @@ -1,94 +0,0 @@ -package app.revanced.patches.youtube.layout.branding.icon.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.branding.icon.annotations.CustomBrandingCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.util.resources.ResourceUtils -import app.revanced.util.resources.ResourceUtils.copyResources -import java.io.File -import java.nio.file.Files - -@Patch -@DependsOn([FixLocaleConfigErrorPatch::class]) -@Name("custom-branding") -@Description("Changes the YouTube launcher icon and name to your choice (defaults to ReVanced).") -@CustomBrandingCompatibility -@Version("0.0.1") -class CustomBrandingPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - fun copyResources(resourceGroups: List) { - iconPath?.let { iconPathString -> - val iconPath = File(iconPathString) - val resourceDirectory = context["res"] - - resourceGroups.forEach { group -> - val fromDirectory = iconPath.resolve(group.resourceDirectoryName) - val toDirectory = resourceDirectory.resolve(group.resourceDirectoryName) - - group.resources.forEach { iconFileName -> - Files.write( - toDirectory.resolve(iconFileName).toPath(), - fromDirectory.resolve(iconFileName).readBytes() - ) - } - } - } ?: resourceGroups.forEach { context.copyResources("branding", it) } - } - - val iconResourceFileNames = arrayOf( - "adaptiveproduct_youtube_background_color_108", - "adaptiveproduct_youtube_foreground_color_108", - "ic_launcher", - "ic_launcher_round" - ).map { "$it.png" }.toTypedArray() - - fun createGroup(directory: String) = ResourceUtils.ResourceGroup( - directory, *iconResourceFileNames - ) - - // change the app icon - arrayOf("xxxhdpi", "xxhdpi", "xhdpi", "hdpi", "mdpi") - .map { "mipmap-$it" } - .map(::createGroup) - .let(::copyResources) - - // change the name of the app - val manifest = context["AndroidManifest.xml"] - manifest.writeText( - manifest.readText() - .replace( - "android:label=\"@string/application_name", - "android:label=\"$appName" - ) - ) - - return PatchResultSuccess() - } - - companion object : OptionsContainer() { - private var appName: String? by option( - PatchOption.StringOption( - key = "appName", - default = "YouTube ReVanced", - title = "Application Name", - description = "The name of the application it will show on your home screen.", - required = true - ) - ) - - private var iconPath: String? by option( - PatchOption.StringOption( - key = "iconPath", - default = null, - title = "App Icon Path", - description = "A path containing mipmap resource folders with icons." - ) - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/annotations/HideButtonsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/annotations/HideButtonsCompatibility.kt deleted file mode 100644 index 7d17a04..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/annotations/HideButtonsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideButtonsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt deleted file mode 100644 index 51a7e1f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/buttons/patch/HideButtonsPatch.kt +++ /dev/null @@ -1,81 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch -import app.revanced.patches.youtube.layout.buttons.annotations.HideButtonsCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([ResourceMappingResourcePatch::class, LithoFilterPatch::class]) -@Name("hide-video-buttons") -@Description("Adds options to hide action buttons under a video.") -@HideButtonsCompatibility -@Version("0.0.1") -class HideButtonsPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - PreferenceScreen( - "revanced_hide_buttons", - StringResource("revanced_hide_buttons_title", "Hide action buttons"), - listOf( - SwitchPreference( - "revanced_like_button", - StringResource("revanced_like_button_title", "Hide like button"), - false, - StringResource("revanced_like_button_on", "Like button is hidden"), - StringResource("revanced_like_button_off", "Like button is shown") - ), - SwitchPreference( - "revanced_dislike_button", - StringResource("revanced_dislike_button_title", "Hide dislike button"), - false, - StringResource("revanced_dislike_button_on", "Dislike button is hidden"), - StringResource("revanced_dislike_button_off", "Dislike button is shown") - ), - SwitchPreference( - "revanced_download_button", - StringResource("revanced_download_button_title", "Hide download button"), - false, - StringResource("revanced_download_button_on", "Download button is hidden"), - StringResource("revanced_download_button_off", "Download button is shown") - ), - SwitchPreference( - "revanced_playlist_button", - StringResource("revanced_playlist_button_title", "Hide playlist button"), - false, - StringResource("revanced_playlist_button_on", "Playlist button is hidden"), - StringResource("revanced_playlist_button_off", "Playlist button is shown") - ), - SwitchPreference( - "revanced_action_button", - StringResource("revanced_action_button_title", "Hide create, clip and thanks buttons"), - true, - StringResource("revanced_action_button_on", "Buttons are hidden"), - StringResource("revanced_action_button_off", "Buttons are shown") - ), - SwitchPreference( - "revanced_share_button", - StringResource("revanced_share_button_title", "Hide share button"), - false, - StringResource("revanced_share_button_on", "Share button is hidden"), - StringResource("revanced_share_button_off", "Share button is shown") - ), - ), - StringResource("revanced_hide_buttons_summary", "Hide or show buttons under videos") - ) - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/annotations/CastPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/annotations/CastPatchCompatibility.kt deleted file mode 100644 index 86adb91..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/annotations/CastPatchCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.castbutton.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CastButtonCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/patch/HideCastButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/patch/HideCastButtonPatch.kt deleted file mode 100644 index c37d2c5..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/castbutton/patch/HideCastButtonPatch.kt +++ /dev/null @@ -1,55 +0,0 @@ -package app.revanced.patches.youtube.layout.castbutton.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.castbutton.annotations.CastButtonCompatibility -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("hide-cast-button") -@Description("Hides the cast button in the video player.") -@CastButtonCompatibility -@Version("0.0.1") -class HideCastButtonPatch : BytecodePatch() { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_cast_button_enabled", - StringResource("revanced_cast_button_enabled_title", "Show cast button"), - false, - StringResource("revanced_cast_button_summary_on", "Cast button is shown"), - StringResource("revanced_cast_button_summary_off", "Cast button is hidden") - ) - ) - - context.classes.forEach { classDef -> - classDef.methods.forEach { method -> - if (classDef.type.endsWith("MediaRouteButton;") && method.name == "setVisibility") { - val setVisibilityMethod = - context.proxy(classDef).mutableClass.methods.first { it.name == "setVisibility" } - - setVisibilityMethod.addInstructions( - 0, """ - invoke-static {p1}, Lapp/revanced/integrations/patches/HideCastButtonPatch;->getCastButtonOverrideV2(I)I - move-result p1 - """ - ) - } - } - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/annotations/CommentsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/comments/annotations/CommentsCompatibility.kt deleted file mode 100644 index fa104ef..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/annotations/CommentsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.comments.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CommentsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt deleted file mode 100644 index 4cc9ef2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/fingerprints/ShortsCommentsButtonFingerprint.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.youtube.layout.comments.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.comments.annotations.CommentsCompatibility -import app.revanced.patches.youtube.layout.comments.resource.patch.CommentsResourcePatch -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("shorts-comments-button-fingerprint") -@CommentsCompatibility -@Version("0.0.1") -object ShortsCommentsButtonFingerprint : MethodFingerprint( - "V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("Z", "Z", "L"), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && (it as WideLiteralInstruction).wideLiteral == CommentsResourcePatch.shortsCommentsButtonId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/patch/CommentsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/patch/CommentsPatch.kt deleted file mode 100644 index ddbcc78..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/bytecode/patch/CommentsPatch.kt +++ /dev/null @@ -1,62 +0,0 @@ -package app.revanced.patches.youtube.layout.comments.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.comments.annotations.CommentsCompatibility -import app.revanced.patches.youtube.layout.comments.bytecode.fingerprints.ShortsCommentsButtonFingerprint -import app.revanced.patches.youtube.layout.comments.resource.patch.CommentsResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class, CommentsResourcePatch::class]) -@Name("comments") -@Description("Hides components related to comments.") -@CommentsCompatibility -@Version("0.0.1") -class CommentsPatch : BytecodePatch( - listOf( - ShortsCommentsButtonFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val shortsCommentsButtonResult = ShortsCommentsButtonFingerprint.result!! - val shortsCommentsButtonMethod = shortsCommentsButtonResult.mutableMethod - - val checkCastAnchorFingerprint = object : MethodFingerprint( - opcodes = listOf( - Opcode.CONST, - Opcode.CONST_HIGH16, - Opcode.IF_EQZ, - Opcode.CONST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - ) - ) {} - - val checkCastAnchorIndex = checkCastAnchorFingerprint.also { - it.resolve(context, shortsCommentsButtonMethod, shortsCommentsButtonResult.classDef) - }.result!!.scanResult.patternScanResult!!.endIndex - - shortsCommentsButtonMethod.addInstructions( - checkCastAnchorIndex + 1, """ - invoke-static {v${(shortsCommentsButtonMethod.instruction(checkCastAnchorIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideShortsCommentsButtonPatch;->hideShortsCommentsButton(Landroid/view/View;)V - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/resource/patch/CommentsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/comments/resource/patch/CommentsResourcePatch.kt deleted file mode 100644 index 4ce5197..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/comments/resource/patch/CommentsResourcePatch.kt +++ /dev/null @@ -1,64 +0,0 @@ -package app.revanced.patches.youtube.layout.comments.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.comments.annotations.CommentsCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Name("comments-resource-patch") -@CommentsCompatibility -@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class CommentsResourcePatch : ResourcePatch { - companion object { - internal var shortsCommentsButtonId: Long = -1 - } - - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - PreferenceScreen( - "revanced_comments", - StringResource("revanced_comments_title", "Comments"), - listOf( - SwitchPreference( - "revanced_hide_comments_section", - StringResource("revanced_hide_comments_section_title", "Remove comments section"), - false, - StringResource("revanced_hide_comments_section_summary_on", "Comment section is hidden"), - StringResource("revanced_hide_comments_section_summary_off", "Comment section is shown") - ), - SwitchPreference( - "revanced_hide_preview_comment", - StringResource("revanced_hide_preview_comment_title", "Hide preview comment"), - false, - StringResource("revanced_hide_preview_comment_on", "Preview comment is hidden"), - StringResource("revanced_hide_preview_comment_off", "Preview comment is shown") - ), - SwitchPreference( - "revanced_hide_shorts_comments_button", - StringResource("revanced_hide_shorts_comments_button_title", "Hide shorts comments button"), - false, - StringResource("revanced_hide_shorts_comments_button_on", "Shorts comments button is hidden"), - StringResource("revanced_hide_shorts_comments_button_off", "Shorts comments button is shown") - ), - ), - StringResource("revanced_comments_summary", "Manage the visibility of comments section components") - ) - ) - - shortsCommentsButtonId = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "drawable" && it.name == "ic_right_comment_32c" - }.id - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/annotations/FullscreenPanelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/annotations/FullscreenPanelsCompatibility.kt deleted file mode 100644 index 5504a05..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/annotations/FullscreenPanelsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.fullscreenpanels.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class FullscreenPanelsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderFingerprint.kt deleted file mode 100644 index d9770ba..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.annotations.ShortsButtonCompatibility -import org.jf.dexlib2.Opcode - -@Name("fullscreen-view-adder-fingerprint") -@ShortsButtonCompatibility -@Version("0.0.1") -object FullscreenViewAdderFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.IGET_BOOLEAN - ) -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderParentFingerprint.kt deleted file mode 100644 index fae2675..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/fingerprints/FullscreenViewAdderParentFingerprint.kt +++ /dev/null @@ -1,24 +0,0 @@ -package app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.annotations.ShortsButtonCompatibility -import org.jf.dexlib2.Opcode - -@Name("fullscreen-view-adder-parent-fingerprint") -@ShortsButtonCompatibility -@Version("0.0.1") -object FullscreenViewAdderParentFingerprint : MethodFingerprint( - parameters = listOf("L", "L"), - opcodes = listOf( - Opcode.GOTO, - Opcode.IGET_BOOLEAN, - Opcode.IF_EQ, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - ), - customFingerprint = { it.definingClass.endsWith("FullscreenEngagementPanelOverlay;") } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/patch/FullscreenPanelsRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/patch/FullscreenPanelsRemoverPatch.kt deleted file mode 100644 index b73d240..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/fullscreenpanels/patch/FullscreenPanelsRemoverPatch.kt +++ /dev/null @@ -1,65 +0,0 @@ -package app.revanced.patches.youtube.layout.fullscreenpanels.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.fullscreenpanels.annotations.FullscreenPanelsCompatibility -import app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints.FullscreenViewAdderFingerprint -import app.revanced.patches.youtube.layout.fullscreenpanels.fingerprints.FullscreenViewAdderParentFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@Name("disable-fullscreen-panels") -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Description("Disables video description and comments panel in fullscreen view.") -@FullscreenPanelsCompatibility -@Version("0.0.1") -class FullscreenPanelsRemoverPatch : BytecodePatch( - listOf( - FullscreenViewAdderParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_fullscreen_panels_enabled", - StringResource("revanced_fullscreen_panels_enabled_title", "Show fullscreen panels"), - false, - StringResource("revanced_fullscreen_panels_summary_on", "Fullscreen panels are shown"), - StringResource("revanced_fullscreen_panels_summary_off", "Fullscreen panels are hidden") - ) - ) - - val parentResult = FullscreenViewAdderParentFingerprint.result!! - FullscreenViewAdderFingerprint.resolve(context, parentResult.method, parentResult.classDef) - val result = FullscreenViewAdderParentFingerprint.result - ?: return PatchResultError("Fingerprint not resolved!") - - val method = result.mutableMethod - - val ifIndex = result.scanResult.patternScanResult!!.startIndex + 2 - - method.removeInstruction(ifIndex) - method.addInstructions( - ifIndex, """ - invoke-static {}, Lapp/revanced/integrations/patches/FullscreenPanelsRemoverPatch;->getFullscreenPanelsVisibility()I - move-result p1 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/annotations/AlbumCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/annotations/AlbumCardsCompatibility.kt deleted file mode 100644 index 207ceea..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/annotations/AlbumCardsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.hidealbumcards.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class AlbumCardsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt deleted file mode 100644 index 695a799..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/fingerprints/AlbumCardsFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.youtube.layout.hidealbumcards.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hidealbumcards.annotations.AlbumCardsCompatibility -import app.revanced.patches.youtube.layout.hidealbumcards.resource.patch.AlbumCardsResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("album-cards-view-fingerprint") -@AlbumCardsCompatibility -@Version("0.0.1") -object AlbumCardsFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == AlbumCardsResourcePatch.albumCardId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/patch/AlbumCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/patch/AlbumCardsPatch.kt deleted file mode 100644 index 9d7593d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/bytecode/patch/AlbumCardsPatch.kt +++ /dev/null @@ -1,45 +0,0 @@ -package app.revanced.patches.youtube.layout.hidealbumcards.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.hidealbumcards.annotations.AlbumCardsCompatibility -import app.revanced.patches.youtube.layout.hidealbumcards.bytecode.fingerprints.AlbumCardsFingerprint -import app.revanced.patches.youtube.layout.hidealbumcards.resource.patch.AlbumCardsResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class, AlbumCardsResourcePatch::class]) -@Name("hide-album-cards") -@Description("Hides the album cards below the artist description.") -@AlbumCardsCompatibility -@Version("0.0.1") -class AlbumCardsPatch : BytecodePatch( - listOf( - AlbumCardsFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val albumCardsResult = AlbumCardsFingerprint.result!! - val albumCardsMethod = albumCardsResult.mutableMethod - - val checkCastAnchorIndex = albumCardsResult.scanResult.patternScanResult!!.endIndex - - albumCardsMethod.addInstruction( - checkCastAnchorIndex + 1, """ - invoke-static {v${(albumCardsMethod.instruction(checkCastAnchorIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideAlbumCardsPatch;->hideAlbumCards(Landroid/view/View;)V - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/resource/patch/AlbumCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/resource/patch/AlbumCardsResourcePatch.kt deleted file mode 100644 index 26ab6bd..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidealbumcards/resource/patch/AlbumCardsResourcePatch.kt +++ /dev/null @@ -1,42 +0,0 @@ -package app.revanced.patches.youtube.layout.hidealbumcards.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.hidealbumcards.annotations.AlbumCardsCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Name("hide-album-cards-resource-patch") -@AlbumCardsCompatibility -@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class AlbumCardsResourcePatch : ResourcePatch { - companion object { - internal var albumCardId: Long = -1 - } - - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_album_cards", - StringResource("revanced_hide_album_cards_title", "Hide the album cards"), - false, - StringResource("revanced_hide_album_cards_summary_on", "Album cards is hidden"), - StringResource("revanced_hide_album_cards_summary_off", "Album cards is visible") - ) - ) - - albumCardId = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "layout" && it.name == "album_card" - }.id - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/annotations/HideArtistCardCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/annotations/HideArtistCardCompatibility.kt deleted file mode 100644 index 264ee2b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/annotations/HideArtistCardCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.buttons.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideArtistCardCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/patch/HideArtistCardPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/patch/HideArtistCardPatch.kt deleted file mode 100644 index ca7b1ac..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideartistcard/patch/HideArtistCardPatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.youtube.layout.hideartistcard.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.litho.filter.patch.LithoFilterPatch -import app.revanced.patches.youtube.layout.buttons.annotations.HideArtistCardCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([ResourceMappingResourcePatch::class, LithoFilterPatch::class]) -@Name("hide-artist-card") -@Description("Hides the artist card below the searchbar.") -@HideArtistCardCompatibility -@Version("0.0.1") -class HideArtistCardPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_artist_card", - StringResource("revanced_hide_hide_artist_card_title", "Hide artist card"), - false, - StringResource("revanced_hide_hide_artist_card_on", "Artist card is hidden"), - StringResource("revanced_hide_hide_artist_card_off", "Artist card is shown") - ), - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecaptionsbutton/patch/HideCaptionsButtonPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidecaptionsbutton/patch/HideCaptionsButtonPatch.kt deleted file mode 100644 index 3e7d105..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecaptionsbutton/patch/HideCaptionsButtonPatch.kt +++ /dev/null @@ -1,56 +0,0 @@ -package app.revanced.patches.youtube.layout.hidecaptionsbutton.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.autocaptions.annotations.AutoCaptionsCompatibility -import app.revanced.patches.youtube.layout.autocaptions.fingerprints.SubtitleButtonControllerFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.Opcode - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("hide-captions-button") -@Description("Hides the captions button on video player.") -@AutoCaptionsCompatibility -@Version("0.0.1") -class HideCaptionsButtonPatch : BytecodePatch(listOf( - SubtitleButtonControllerFingerprint, -)) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_captions_button", - StringResource("revanced_hide_captions_button_title", "Hide captions button"), - false, - StringResource("revanced_hide_captions_button_summary_on", "Captions button is hidden"), - StringResource("revanced_hide_captions_button_summary_off", "Captions button is shown") - ) - ) - - val subtitleButtonControllerMethod = SubtitleButtonControllerFingerprint.result!!.mutableMethod - - // Due to previously applied patches, scanResult index cannot be used in this context - val igetBooleanIndex = subtitleButtonControllerMethod.implementation!!.instructions.indexOfFirst { - it.opcode == Opcode.IGET_BOOLEAN - } - - subtitleButtonControllerMethod.addInstructions( - igetBooleanIndex + 1, """ - invoke-static {v0}, Lapp/revanced/integrations/patches/HideCaptionsButtonPatch;->hideCaptionsButton(Landroid/widget/ImageView;)V - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt deleted file mode 100644 index 60c9681..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/annotations/CrowdfundingBoxCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.hidecrowdfundingbox.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CrowdfundingBoxCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt deleted file mode 100644 index 1f34bcb..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/fingerprints/CrowdfundingBoxFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.youtube.layout.hidecrowdfundingbox.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hidecrowdfundingbox.annotations.CrowdfundingBoxCompatibility -import app.revanced.patches.youtube.layout.hidecrowdfundingbox.resource.patch.CrowdfundingBoxResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("crowdfunding-box-view-parent-fingerprint") -@CrowdfundingBoxCompatibility -@Version("0.0.1") -object CrowdfundingBoxFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.CONST_4, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == CrowdfundingBoxResourcePatch.crowdfundingBoxId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt deleted file mode 100644 index 0058318..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/bytecode/patch/CrowdfundingBoxPatch.kt +++ /dev/null @@ -1,46 +0,0 @@ -package app.revanced.patches.youtube.layout.hidecrowdfundingbox.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.hidecrowdfundingbox.resource.patch.CrowdfundingBoxResourcePatch -import app.revanced.patches.youtube.layout.hidecrowdfundingbox.annotations.CrowdfundingBoxCompatibility -import app.revanced.patches.youtube.layout.hidecrowdfundingbox.bytecode.fingerprints.CrowdfundingBoxFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class, CrowdfundingBoxResourcePatch::class]) -@Name("hide-crowdfunding-box") -@Description("Hides the crowdfunding box between the player and video description.") -@CrowdfundingBoxCompatibility -@Version("0.0.1") -class CrowdfundingBoxPatch : BytecodePatch( - listOf( - CrowdfundingBoxFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val crowdfundingBoxResult = CrowdfundingBoxFingerprint.result!! - val crowdfundingBoxMethod = crowdfundingBoxResult.mutableMethod - - val moveResultObjectIndex = - crowdfundingBoxResult.scanResult.patternScanResult!!.endIndex - 2 - - crowdfundingBoxMethod.addInstruction( - moveResultObjectIndex + 1, """ - invoke-static {v${(crowdfundingBoxMethod.instruction(moveResultObjectIndex) as OneRegisterInstruction).registerA}}, Lapp/revanced/integrations/patches/HideCrowdfundingBoxPatch;->hideCrowdfundingBox(Landroid/view/View;)V - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt deleted file mode 100644 index 784b31a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidecrowdfundingbox/resource/patch/CrowdfundingBoxResourcePatch.kt +++ /dev/null @@ -1,42 +0,0 @@ -package app.revanced.patches.youtube.layout.hidecrowdfundingbox.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.hidecrowdfundingbox.annotations.CrowdfundingBoxCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Name("crowdfunding-box-resource-patch") -@CrowdfundingBoxCompatibility -@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class CrowdfundingBoxResourcePatch : ResourcePatch { - companion object { - internal var crowdfundingBoxId: Long = -1 - } - - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_crowdfunding_box", - StringResource("revanced_hide_crowdfunding_box_title", "Hide the crowdfunding box"), - false, - StringResource("revanced_hide_crowdfunding_box_summary_on", "Crowdfunding box is hidden"), - StringResource("revanced_hide_crowdfunding_box_summary_off", "Crowdfunding box is visible") - ) - ) - - crowdfundingBoxId = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "layout" && it.name == "donation_companion" - }.id - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt deleted file mode 100644 index ec0e381..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/annotations/HideEndScreenCardsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.hideendscreencards.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideEndscreenCardsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt deleted file mode 100644 index 722aa62..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutCircleFingerprint.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility -import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("layout-circle-fingerprint") -@HideEndscreenCardsCompatibility -@Version("0.0.1") -object LayoutCircleFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutCircle - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt deleted file mode 100644 index dc59051..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutIconFingerprint.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility -import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("layout-icon-fingerprint") -@HideEndscreenCardsCompatibility -@Version("0.0.1") -object LayoutIconFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.CONST_4, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutIcon - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt deleted file mode 100644 index ca4d2e8..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/fingerprints/LayoutVideoFingerprint.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility -import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("layout-video-fingerprint") -@HideEndscreenCardsCompatibility -@Version("0.0.1") -object LayoutVideoFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == HideEndscreenCardsResourcePatch.layoutVideo - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt deleted file mode 100644 index 8bef7a9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/bytecode/patch/HideEndscreenCardsPatch.kt +++ /dev/null @@ -1,57 +0,0 @@ -package app.revanced.patches.youtube.layout.hideendscreencards.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.Fingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility -import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutCircleFingerprint -import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutIconFingerprint -import app.revanced.patches.youtube.layout.hideendscreencards.bytecode.fingerprints.LayoutVideoFingerprint -import app.revanced.patches.youtube.layout.hideendscreencards.resource.patch.HideEndscreenCardsResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.iface.instruction.formats.Instruction21c - -@Patch -@DependsOn([IntegrationsPatch::class, HideEndscreenCardsResourcePatch::class]) -@Name("hide-endscreen-cards") -@Description("Hides the suggested video cards at the end of a video in fullscreen.") -@HideEndscreenCardsCompatibility -@Version("0.0.1") -class HideEndscreenCardsPatch : BytecodePatch( - listOf( - LayoutCircleFingerprint, - LayoutIconFingerprint, - LayoutVideoFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - fun MethodFingerprint.injectHideCall() { - val layoutResult = result!! - val layoutMethod = layoutResult.mutableMethod - - val checkCastIndex = layoutResult.scanResult.patternScanResult!!.endIndex - val viewRegister = (layoutMethod.instruction(checkCastIndex) as Instruction21c).registerA - - layoutMethod.addInstruction( - checkCastIndex + 1, - "invoke-static { v$viewRegister }, Lapp/revanced/integrations/patches/HideEndscreenCardsPatch;->hideEndscreen(Landroid/view/View;)V" - ) - } - - listOf(LayoutCircleFingerprint, LayoutIconFingerprint, LayoutVideoFingerprint).forEach(MethodFingerprint::injectHideCall) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt deleted file mode 100644 index c5404d3..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideendscreencards/resource/patch/HideEndscreenCardsResourcePatch.kt +++ /dev/null @@ -1,48 +0,0 @@ -package app.revanced.patches.youtube.layout.hideendscreencards.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.hideendscreencards.annotations.HideEndscreenCardsCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Name("hide-endscreen-cards-resource-patch") -@HideEndscreenCardsCompatibility -@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class HideEndscreenCardsResourcePatch : ResourcePatch { - internal companion object { - var layoutCircle: Long = -1 - var layoutIcon: Long = -1 - var layoutVideo: Long = -1 - } - - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_endscreen_cards", - StringResource("revanced_hide_endscreen_cards_title", "Hide end-screen cards"), - true, - StringResource("revanced_hide_endscreen_cards_summary_on", "End-screen cards are hidden"), - StringResource("revanced_hide_endscreen_cards_summary_off", "End-screen cards are shown") - ), - ) - - fun findEndscreenResourceId(name: String) = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "layout" && it.name == "endscreen_element_layout_$name" - }.id - - layoutCircle = findEndscreenResourceId("circle") - layoutIcon = findEndscreenResourceId("icon") - layoutVideo = findEndscreenResourceId("video") - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/annotations/HideInfocardsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/annotations/HideInfocardsCompatibility.kt deleted file mode 100644 index 4c9049d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/annotations/HideInfocardsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.hideinfocards.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideInfocardsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoFingerprint.kt deleted file mode 100644 index cf034ef..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.hideinfocards.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hideinfocards.annotations.HideInfocardsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("infocards-incognito-fingerprint") -@HideInfocardsCompatibility -@Version("0.0.1") -object InfocardsIncognitoFingerprint : MethodFingerprint( - "Ljava/lang/Boolean;", - AccessFlags.PUBLIC or AccessFlags.FINAL, - strings = listOf("vibrator") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoParentFingerprint.kt deleted file mode 100644 index 4de1fd6..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsIncognitoParentFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.hideinfocards.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hideinfocards.annotations.HideInfocardsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("infocards-incognito-parent-fingerprint") -@HideInfocardsCompatibility -@Version("0.0.1") -object InfocardsIncognitoParentFingerprint : MethodFingerprint( - "Ljava/lang/String;", - AccessFlags.PUBLIC or AccessFlags.FINAL, - strings = listOf("player_overlay_info_card_teaser"), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsMethodCallFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsMethodCallFingerprint.kt deleted file mode 100644 index a5f4178..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/fingerprints/InfocardsMethodCallFingerprint.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.revanced.patches.youtube.layout.hideinfocards.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hideinfocards.annotations.HideInfocardsCompatibility -import app.revanced.patches.youtube.layout.hideinfocards.resource.patch.HideInfocardsResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("infocards-method-call-fingerprint") -@HideInfocardsCompatibility -@Version("0.0.1") -object InfocardsMethodCallFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - (instruction as? WideLiteralInstruction)?.wideLiteral == HideInfocardsResourcePatch.drawerResourceId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/patch/HideInfocardsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/patch/HideInfocardsPatch.kt deleted file mode 100644 index 9d5f040..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/patch/HideInfocardsPatch.kt +++ /dev/null @@ -1,77 +0,0 @@ -package app.revanced.patches.youtube.layout.hideinfocards.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.layout.hideinfocards.annotations.HideInfocardsCompatibility -import app.revanced.patches.youtube.layout.hideinfocards.fingerprints.InfocardsIncognitoFingerprint -import app.revanced.patches.youtube.layout.hideinfocards.fingerprints.InfocardsIncognitoParentFingerprint -import app.revanced.patches.youtube.layout.hideinfocards.fingerprints.InfocardsMethodCallFingerprint -import app.revanced.patches.youtube.layout.hideinfocards.resource.patch.HideInfocardsResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction35c - -@Patch -@DependsOn([IntegrationsPatch::class, HideInfocardsResourcePatch::class]) -@Name("hide-info-cards") -@Description("Hides info-cards in videos.") -@HideInfocardsCompatibility -@Version("0.0.1") -class HideInfocardsPatch : BytecodePatch( - listOf( - InfocardsIncognitoParentFingerprint, - InfocardsMethodCallFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - with(InfocardsIncognitoFingerprint.also { - it.resolve(context, InfocardsIncognitoParentFingerprint.result!!.classDef) - }.result!!.mutableMethod) { - val invokeInstructionIndex = implementation!!.instructions.indexOfFirst { - it.opcode.ordinal == Opcode.INVOKE_VIRTUAL.ordinal && - ((it as? BuilderInstruction35c)?.reference.toString() == - "Landroid/view/View;->setVisibility(I)V") - } - - replaceInstruction( - invokeInstructionIndex, - "invoke-static {v${(instruction(invokeInstructionIndex) as? BuilderInstruction35c)?.registerC}}," + - " Lapp/revanced/integrations/patches/HideInfocardsPatch;->hideInfocardsIncognito(Landroid/view/View;)V" - ) - } - - with(InfocardsMethodCallFingerprint.result!!) { - val hideInfocardsCallMethod = mutableMethod - - val invokeInterfaceIndex = scanResult.patternScanResult!!.endIndex - val toggleRegister = hideInfocardsCallMethod.implementation!!.registerCount - 1 - - hideInfocardsCallMethod.addInstructions( - invokeInterfaceIndex, """ - invoke-static {}, Lapp/revanced/integrations/patches/HideInfocardsPatch;->hideInfocardsMethodCall()Z - move-result v$toggleRegister - if-nez v$toggleRegister, :hide_info_cards - """, - listOf( - ExternalLabel( - "hide_info_cards", hideInfocardsCallMethod.instruction(invokeInterfaceIndex + 1) - ) - ) - ) - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/resource/patch/HideInfocardsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/resource/patch/HideInfocardsResourcePatch.kt deleted file mode 100644 index e7f12a9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hideinfocards/resource/patch/HideInfocardsResourcePatch.kt +++ /dev/null @@ -1,40 +0,0 @@ -package app.revanced.patches.youtube.layout.hideinfocards.resource.patch - -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.hideinfocards.annotations.HideInfocardsCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@HideInfocardsCompatibility -@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class HideInfocardsResourcePatch : ResourcePatch { - internal companion object { - var drawerResourceId: Long = -1 - } - - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_infocards", - StringResource("revanced_hide_infocards_title", "Hide info-cards"), - true, - StringResource("revanced_hide_infocards_summary_on", "Info-cards are hidden"), - StringResource("revanced_hide_infocards_summary_off", "Info-cards are shown") - ) - ) - - drawerResourceId = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "id" && it.name == "info_cards_drawer_header" - }.id - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/annotations/MixPlaylistsPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/annotations/MixPlaylistsPatchCompatibility.kt deleted file mode 100644 index fde52ac..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/annotations/MixPlaylistsPatchCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.hidemixplaylists.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.36.39", "17.37.35", "17.38.36", "17.39.35", "17.40.41", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MixPlaylistsPatchCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/CreateMixPlaylistFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/CreateMixPlaylistFingerprint.kt deleted file mode 100644 index 27390c3..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/CreateMixPlaylistFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.layout.hidemixplaylists.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hidemixplaylists.annotations.MixPlaylistsPatchCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("create-mix-playlist-fingerprint") -@MixPlaylistsPatchCompatibility -@Version("0.0.1") -object CreateMixPlaylistFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - ) -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/SecondCreateMixPlaylistFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/SecondCreateMixPlaylistFingerprint.kt deleted file mode 100644 index f2e995c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/fingerprints/SecondCreateMixPlaylistFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.layout.hidemixplaylists.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hidemixplaylists.annotations.MixPlaylistsPatchCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("second-create-mix-playlist-fingerprint") -@MixPlaylistsPatchCompatibility -@Version("0.0.1") -object SecondCreateMixPlaylistFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, listOf("L", "L", "L", "L", "L", "L"), listOf( - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/patch/MixPlaylistsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/patch/MixPlaylistsPatch.kt deleted file mode 100644 index c6f692b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidemixplaylists/patch/MixPlaylistsPatch.kt +++ /dev/null @@ -1,64 +0,0 @@ -package app.revanced.patches.youtube.layout.hidemixplaylists.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patches.youtube.layout.hidemixplaylists.annotations.MixPlaylistsPatchCompatibility -import app.revanced.patches.youtube.layout.hidemixplaylists.fingerprints.CreateMixPlaylistFingerprint -import app.revanced.patches.youtube.layout.hidemixplaylists.fingerprints.SecondCreateMixPlaylistFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class]) -@Name("hide-my-mix") -@Description("Hides mix playlists.") -@MixPlaylistsPatchCompatibility -@Version("0.0.1") -class MixPlaylistsPatch : BytecodePatch( - listOf( - CreateMixPlaylistFingerprint, SecondCreateMixPlaylistFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_mix_playlists_hidden", - StringResource("revanced_mix_playlists_title", "Hide mix playlists"), - false, - StringResource("revanced_mix_playlists_summary_on", "Mix playlists are hidden"), - StringResource("revanced_mix_playlists_summary_off", "Mix playlists are shown") - ) - ) - - arrayOf(CreateMixPlaylistFingerprint, SecondCreateMixPlaylistFingerprint).forEach(::addHook) - - return PatchResultSuccess() - } - - private fun addHook(fingerprint: MethodFingerprint) { - with (fingerprint.result!!) { - val insertIndex = scanResult.patternScanResult!!.endIndex - 3 - - val register = (mutableMethod.instruction(insertIndex - 2) as OneRegisterInstruction).registerA - - mutableMethod.addInstruction( - insertIndex, - "invoke-static {v$register}, Lapp/revanced/integrations/patches/HideMixPlaylistsPatch;->hideMixPlaylists(Landroid/view/View;)V" - ) - } - - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/annotations/HideTimeAndSeekbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/annotations/HideTimeAndSeekbarCompatibility.kt deleted file mode 100644 index 0285726..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/annotations/HideTimeAndSeekbarCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.hidetimeandseekbar.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideTimeAndSeekbarCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/fingerprints/TimeCounterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/fingerprints/TimeCounterFingerprint.kt deleted file mode 100644 index a619add..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/fingerprints/TimeCounterFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.layout.hidetimeandseekbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.hidetimeandseekbar.annotations.HideTimeAndSeekbarCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("time-counter-fingerprint") -@FuzzyPatternScanMethod(3) -@HideTimeAndSeekbarCompatibility -@Version("0.0.1") -object TimeCounterFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), listOf( - Opcode.IGET_OBJECT, - Opcode.IGET_WIDE, - Opcode.CONST_WIDE_16, - Opcode.CMP_LONG, - Opcode.IF_LEZ, - Opcode.IGET_OBJECT, - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.GOTO, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/patch/HideTimeAndSeekbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/patch/HideTimeAndSeekbarPatch.kt deleted file mode 100644 index 09a221e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/hidetimeandseekbar/patch/HideTimeAndSeekbarPatch.kt +++ /dev/null @@ -1,72 +0,0 @@ -package app.revanced.patches.youtube.layout.hidetimeandseekbar.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.hidetimeandseekbar.annotations.HideTimeAndSeekbarCompatibility -import app.revanced.patches.youtube.layout.hidetimeandseekbar.fingerprints.TimeCounterFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.CreateVideoPlayerSeekbarFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("hide-time-and-seekbar") -@Description("Hides progress bar and time counter on videos.") -@HideTimeAndSeekbarCompatibility -@Version("0.0.1") -class HideTimeAndSeekbarPatch : BytecodePatch( - listOf( - CreateVideoPlayerSeekbarFingerprint, TimeCounterFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_time_and_seekbar", - StringResource("revanced_hide_time_and_seekbar_title", "Hide time and seekbar"), - false, - StringResource("revanced_hide_time_and_seekbar_summary_on", "Time and seekbar are hidden"), - StringResource("revanced_hide_time_and_seekbar_summary_off", "Time and seekbar are visible") - ) - ) - - val createVideoPlayerSeekbarMethod = CreateVideoPlayerSeekbarFingerprint.result!!.mutableMethod - - createVideoPlayerSeekbarMethod.addInstructions( - 0, """ - const/4 v0, 0x0 - invoke-static { }, Lapp/revanced/integrations/patches/HideTimeAndSeekbarPatch;->hideTimeAndSeekbar()Z - move-result v0 - if-eqz v0, :hide_time_and_seekbar - return-void - :hide_time_and_seekbar - nop - """ - ) - - val timeCounterMethod = TimeCounterFingerprint.result!!.mutableMethod - - timeCounterMethod.addInstructions( - 0, """ - invoke-static { }, Lapp/revanced/integrations/patches/HideTimeAndSeekbarPatch;->hideTimeAndSeekbar()Z - move-result v0 - if-eqz v0, :hide_time_and_seekbar - return-void - :hide_time_and_seekbar - nop - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt deleted file mode 100644 index 0c831a7..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/annotations/OldQualityLayoutCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.oldqualitylayout.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class OldQualityLayoutCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt deleted file mode 100644 index aa6ccdf..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/fingerprints/QualityMenuViewInflateFingerprint.kt +++ /dev/null @@ -1,37 +0,0 @@ -package app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("quality-menu-view-inflate-fingerprint") -@OldQualityLayoutCompatibility -@Version("0.0.1") -object QualityMenuViewInflateFingerprint : MethodFingerprint( - "L", AccessFlags.FINAL or AccessFlags.PUBLIC, listOf("L", "L", "L"), listOf( - Opcode.INVOKE_SUPER, - Opcode.CONST, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.CONST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CONST_STRING, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt deleted file mode 100644 index 581b3c1..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/oldqualitylayout/patch/OldQualityLayoutPatch.kt +++ /dev/null @@ -1,59 +0,0 @@ -package app.revanced.patches.youtube.layout.oldqualitylayout.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.oldqualitylayout.annotations.OldQualityLayoutCompatibility -import app.revanced.patches.youtube.layout.oldqualitylayout.fingerprints.QualityMenuViewInflateFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("old-quality-layout") -@Description("Enables the original quality flyout menu.") -@OldQualityLayoutCompatibility -@Version("0.0.1") -class OldQualityLayoutPatch : BytecodePatch( - listOf(QualityMenuViewInflateFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_use_old_style_quality_settings", - StringResource("revanced_old_style_quality_settings_enabled_title", "Use old quality layout"), - true, - StringResource("revanced_old_style_quality_settings_summary_on", "Old quality settings are shown"), - StringResource("revanced_old_style_quality_settings_summary_off", "New quality settings are shown") - ) - ) - - val inflateFingerprintResult = QualityMenuViewInflateFingerprint.result!! - val method = inflateFingerprintResult.mutableMethod - val instructions = method.implementation!!.instructions - - // at this index the listener is added to the list view - val listenerInvokeRegister = instructions.size - 1 - 1 - - // get the register which stores the quality menu list view - val onItemClickViewRegister = (instructions[listenerInvokeRegister] as FiveRegisterInstruction).registerC - - // insert the integrations method - method.addInstruction( - listenerInvokeRegister, // insert the integrations instructions right before the listener - "invoke-static { v$onItemClickViewRegister }, Lapp/revanced/integrations/patches/playback/quality/OldQualityLayoutPatch;->showOldQualityMenu(Landroid/widget/ListView;)V" - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/annotations/HideEmailAddressCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/annotations/HideEmailAddressCompatibility.kt deleted file mode 100644 index a163f00..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/annotations/HideEmailAddressCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.personalinformation.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideEmailAddressCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt deleted file mode 100644 index bda32dd..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/fingerprints/AccountSwitcherAccessibilityLabelFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.layout.personalinformation.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.personalinformation.annotations.HideEmailAddressCompatibility -import app.revanced.patches.youtube.layout.personalinformation.resource.patch.HideEmailAddressResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("account-switcher-accessibility-label-fingerprint") -@HideEmailAddressCompatibility -@Version("0.0.1") -object AccountSwitcherAccessibilityLabelFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.NEW_ARRAY, - Opcode.CONST_4, - Opcode.APUT_OBJECT, - Opcode.CONST, - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == HideEmailAddressResourcePatch.accountSwitcherAccessibilityLabelId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/patch/HideEmailAddressPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/patch/HideEmailAddressPatch.kt deleted file mode 100644 index 46234db..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/bytecode/patch/HideEmailAddressPatch.kt +++ /dev/null @@ -1,53 +0,0 @@ -package app.revanced.patches.youtube.layout.personalinformation.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.layout.personalinformation.annotations.HideEmailAddressCompatibility -import app.revanced.patches.youtube.layout.personalinformation.bytecode.fingerprints.AccountSwitcherAccessibilityLabelFingerprint -import app.revanced.patches.youtube.layout.personalinformation.resource.patch.HideEmailAddressResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class, HideEmailAddressResourcePatch::class]) -@Name("hide-email-address") -@Description("Hides the email address in the account switcher.") -@HideEmailAddressCompatibility -@Version("0.0.1") -class HideEmailAddressPatch : BytecodePatch( - listOf( - AccountSwitcherAccessibilityLabelFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val accountSwitcherAccessibilityLabelResult = AccountSwitcherAccessibilityLabelFingerprint.result!! - val accountSwitcherAccessibilityLabelMethod = accountSwitcherAccessibilityLabelResult.mutableMethod - - val setVisibilityConstIndex = - accountSwitcherAccessibilityLabelResult.scanResult.patternScanResult!!.endIndex - - val setVisibilityConstRegister = ( - accountSwitcherAccessibilityLabelMethod.instruction - (setVisibilityConstIndex - 2) as OneRegisterInstruction - ).registerA - - accountSwitcherAccessibilityLabelMethod.addInstructions( - setVisibilityConstIndex, """ - invoke-static {v$setVisibilityConstRegister}, Lapp/revanced/integrations/patches/HideEmailAddressPatch;->hideEmailAddress(I)I - move-result v$setVisibilityConstRegister - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt deleted file mode 100644 index bb56bb0..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/personalinformation/resource/patch/HideEmailAddressResourcePatch.kt +++ /dev/null @@ -1,42 +0,0 @@ -package app.revanced.patches.youtube.layout.personalinformation.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.personalinformation.annotations.HideEmailAddressCompatibility -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Name("hide-email-address-resource-patch") -@HideEmailAddressCompatibility -@DependsOn([SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class HideEmailAddressResourcePatch : ResourcePatch { - companion object { - internal var accountSwitcherAccessibilityLabelId: Long = -1 - } - - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_email_address", - StringResource("revanced_hide_email_address_title", "Hide the email address"), - false, - StringResource("revanced_hide_email_address_summary_on", "Email address is hidden"), - StringResource("revanced_hide_email_address_summary_off", "Email address is visible") - ) - ) - - accountSwitcherAccessibilityLabelId = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "string" && it.name == "account_switcher_accessibility_label" - }.id - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/annotations/CreateButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/annotations/CreateButtonCompatibility.kt deleted file mode 100644 index 64adf4c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/annotations/CreateButtonCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.createbutton.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CreateButtonCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/fingerprints/PivotBarCreateButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/fingerprints/PivotBarCreateButtonViewFingerprint.kt deleted file mode 100644 index 6f0720d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/fingerprints/PivotBarCreateButtonViewFingerprint.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.createbutton.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.pivotbar.createbutton.annotations.CreateButtonCompatibility -import org.jf.dexlib2.Opcode - -@Name("pivot-bar-create-button-view-fingerprint") -@CreateButtonCompatibility -@Version("0.0.1") -object PivotBarCreateButtonViewFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_DIRECT_RANGE, // unique instruction anchor - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/patch/CreateButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/patch/CreateButtonRemoverPatch.kt deleted file mode 100644 index d9ac146..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/createbutton/patch/CreateButtonRemoverPatch.kt +++ /dev/null @@ -1,72 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.createbutton.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.MethodFingerprintExtensions.name -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.pivotbar.createbutton.annotations.CreateButtonCompatibility -import app.revanced.patches.youtube.layout.pivotbar.createbutton.fingerprints.PivotBarCreateButtonViewFingerprint -import app.revanced.patches.youtube.layout.pivotbar.fingerprints.PivotBarFingerprint -import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.injectHook -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, ResourceMappingResourcePatch::class, SettingsPatch::class]) -@Name("hide-create-button") -@Description("Hides the create button in the navigation bar.") -@CreateButtonCompatibility -@Version("0.0.1") -class CreateButtonRemoverPatch : BytecodePatch( - listOf( - PivotBarFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_create_button_enabled", - StringResource("revanced_create_button_enabled_title", "Show create button"), - false, - StringResource("revanced_create_button_summary_on", "Create button is shown"), - StringResource("revanced_create_button_summary_off", "Create button is hidden") - ) - ) - - /* - * Resolve fingerprints - */ - - val pivotBarResult = PivotBarFingerprint.result ?: return PatchResultError("PivotBarFingerprint failed") - - if (!PivotBarCreateButtonViewFingerprint.resolve(context, pivotBarResult.mutableMethod, pivotBarResult.mutableClass)) - return PatchResultError("${PivotBarCreateButtonViewFingerprint.name} failed") - - val createButtonResult = PivotBarCreateButtonViewFingerprint.result!! - val insertIndex = createButtonResult.scanResult.patternScanResult!!.endIndex - - /* - * Inject hooks - */ - - val integrationsClass = "Lapp/revanced/integrations/patches/HideCreateButtonPatch;" - val hook = - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, $integrationsClass->hideCreateButton(Landroid/view/View;)V" - - createButtonResult.mutableMethod.injectHook(hook, insertIndex) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/fingerprints/PivotBarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/fingerprints/PivotBarFingerprint.kt deleted file mode 100644 index f7cfb5f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/fingerprints/PivotBarFingerprint.kt +++ /dev/null @@ -1,50 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("pivot-bar-fingerprint") -@FuzzyPatternScanMethod(2) -// TODO: This fingerprint is used in multiple patches, so technically two compatibilities are needed -// @CreateButtonCompatibility -@Version("0.0.1") -object PivotBarFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("Z"), - listOf( - Opcode.IGET, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.CONST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.MOVE_OBJECT, - Opcode.INVOKE_DIRECT_RANGE, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/annotations/ShortsButtonCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/annotations/ShortsButtonCompatibility.kt deleted file mode 100644 index edf4d36..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/annotations/ShortsButtonCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.shortsbutton.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ShortsButtonCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarEnumFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarEnumFingerprint.kt deleted file mode 100644 index 33ddcfc..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarEnumFingerprint.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.shortsbutton.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.annotations.ShortsButtonCompatibility -import org.jf.dexlib2.Opcode - -@Name("pivot-bar-enum-fingerprint") -@ShortsButtonCompatibility -@Version("0.0.1") -object PivotBarEnumFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IF_NEZ, // target reference - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarShortsButtonViewFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarShortsButtonViewFingerprint.kt deleted file mode 100644 index af9e244..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/fingerprints/PivotBarShortsButtonViewFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.shortsbutton.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.annotations.ShortsButtonCompatibility -import org.jf.dexlib2.Opcode - -@Name("pivot-bar-shorts-button-view-fingerprint") -@ShortsButtonCompatibility -@Version("0.0.1") -object PivotBarShortsButtonViewFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_VIRTUAL_RANGE, - Opcode.MOVE_RESULT_OBJECT, // target reference - Opcode.GOTO, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/patch/ShortsButtonRemoverPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/patch/ShortsButtonRemoverPatch.kt deleted file mode 100644 index dd20a3c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/shortsbutton/patch/ShortsButtonRemoverPatch.kt +++ /dev/null @@ -1,90 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.shortsbutton.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.MethodFingerprintExtensions.name -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.pivotbar.fingerprints.PivotBarFingerprint -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.annotations.ShortsButtonCompatibility -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.fingerprints.PivotBarEnumFingerprint -import app.revanced.patches.youtube.layout.pivotbar.shortsbutton.fingerprints.PivotBarShortsButtonViewFingerprint -import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.REGISTER_TEMPLATE_REPLACEMENT -import app.revanced.patches.youtube.layout.pivotbar.utils.InjectionUtils.injectHook -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("hide-shorts-button") -@Description("Hides the shorts button on the navigation bar.") -@ShortsButtonCompatibility -@Version("0.0.1") -class ShortsButtonRemoverPatch : BytecodePatch( - listOf(PivotBarFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_shorts_button_enabled", - StringResource("revanced_shorts_button_enabled_title", "Show shorts button"), - false, - StringResource("revanced_shorts_button_summary_on", "Shorts button is shown"), - StringResource("revanced_shorts_button_summary_off", "Shorts button is hidden") - ) - ) - - /* - * Resolve fingerprints - */ - - val pivotBarResult = PivotBarFingerprint.result ?: return PatchResultError("PivotBarFingerprint failed") - val fingerprintResults = arrayOf(PivotBarEnumFingerprint, PivotBarShortsButtonViewFingerprint) - .onEach { - val resolutionSucceeded = it.resolve( - context, - pivotBarResult.mutableMethod, - pivotBarResult.mutableClass - ) - - if (!resolutionSucceeded) return PatchResultError("${it.name} failed") - } - .map { it.result!!.scanResult.patternScanResult!! } - - val enumScanResult = fingerprintResults[0] - val buttonViewResult = fingerprintResults[1] - - val enumHookInsertIndex = enumScanResult.startIndex + 2 - val buttonHookInsertIndex = buttonViewResult.endIndex - - /* - * Inject hooks - */ - - val integrationsClass = "Lapp/revanced/integrations/patches/HideShortsButtonPatch;" - - val enumHook = - "sput-object v$REGISTER_TEMPLATE_REPLACEMENT, $integrationsClass->lastPivotTab:Ljava/lang/Enum;" - val buttonHook = - "invoke-static { v$REGISTER_TEMPLATE_REPLACEMENT }, $integrationsClass->hideShortsButton(Landroid/view/View;)V" - - // Inject bottom to top to not mess up the indices - mapOf( - buttonHook to buttonHookInsertIndex, - enumHook to enumHookInsertIndex - ).forEach { (hook, insertIndex) -> - pivotBarResult.mutableMethod.injectHook(hook, insertIndex) - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/utils/InjectionUtils.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/utils/InjectionUtils.kt deleted file mode 100644 index 8667b10..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/pivotbar/utils/InjectionUtils.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.layout.pivotbar.utils - -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import org.jf.dexlib2.Opcode.MOVE_RESULT_OBJECT -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -internal object InjectionUtils { - const val REGISTER_TEMPLATE_REPLACEMENT: String = "REGISTER_INDEX" - - /** - * Injects an instruction into insertIndex of the hook. - * @param hook The hook to insert. - * @param insertIndex The index to insert the instruction at. - * [MOVE_RESULT_OBJECT] has to be the previous instruction before [insertIndex]. - */ - fun MutableMethod.injectHook(hook: String, insertIndex: Int) { - val injectTarget = this - - // Register to pass to the hook - val registerIndex = insertIndex - 1 // MOVE_RESULT_OBJECT is always the previous instruction - val register = (injectTarget.instruction(registerIndex) as OneRegisterInstruction).registerA - - injectTarget.addInstruction( - insertIndex, - hook.replace("REGISTER_INDEX", register.toString()), - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/annotations/PlayerPopupPanelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/annotations/PlayerPopupPanelsCompatibility.kt deleted file mode 100644 index fb47ef4..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/annotations/PlayerPopupPanelsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.playerpopuppanels.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PlayerPopupPanelsCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/fingerprints/EngagementPanelControllerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/fingerprints/EngagementPanelControllerFingerprint.kt deleted file mode 100644 index efc3ecd..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/fingerprints/EngagementPanelControllerFingerprint.kt +++ /dev/null @@ -1,41 +0,0 @@ -package app.revanced.patches.youtube.layout.playerpopuppanels.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.playerpopuppanels.annotations.PlayerPopupPanelsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("engagement-player-controller-fingerprint") -@FuzzyPatternScanMethod(3) -@PlayerPopupPanelsCompatibility -@Version("0.0.1") -object EngagementPanelControllerFingerprint : MethodFingerprint( - "L", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("L", "L", "Z", "Z", "Z"), listOf( - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_FROM16, - Opcode.IGET_BOOLEAN, - Opcode.CONST_4, - Opcode.IF_NEZ, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.SGET_OBJECT, - Opcode.SGET_OBJECT, - Opcode.CONST_STRING, - Opcode.INVOKE_STATIC, - Opcode.RETURN_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_4, - Opcode.CONST_4, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/patch/PlayerPopupPanelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/patch/PlayerPopupPanelsPatch.kt deleted file mode 100644 index 8cce12f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/playerpopuppanels/patch/PlayerPopupPanelsPatch.kt +++ /dev/null @@ -1,59 +0,0 @@ -package app.revanced.patches.youtube.layout.playerpopuppanels.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.playerpopuppanels.annotations.PlayerPopupPanelsCompatibility -import app.revanced.patches.youtube.layout.playerpopuppanels.fingerprints.EngagementPanelControllerFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("disable-auto-player-popup-panels") -@Description("Disable automatic popup panels (playlist or live chat) on video player.") -@PlayerPopupPanelsCompatibility -@Version("0.0.1") -class PlayerPopupPanelsPatch : BytecodePatch( - listOf( - EngagementPanelControllerFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_player_popup_panels_enabled", - StringResource("revanced_player_popup_panels_title", "Disable player popup panels"), - false, - StringResource("revanced_player_popup_panels_summary_on", "Player popup panels are disabled"), - StringResource("revanced_player_popup_panels_summary_off", "Player popup panels are enabled") - ) - ) - - val engagementPanelControllerMethod = EngagementPanelControllerFingerprint.result!!.mutableMethod - - engagementPanelControllerMethod.addInstructions( - 0, """ - invoke-static { }, Lapp/revanced/integrations/patches/DisablePlayerPopupPanelsPatch;->disablePlayerPopupPanels()Z - move-result v0 - if-eqz v0, :player_popup_panels - if-eqz p4, :player_popup_panels - const/4 v0, 0x0 - return-object v0 - :player_popup_panels - nop - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt deleted file mode 100644 index b05aef0..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/annotations/HideReelsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.reels.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideReelsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/fingerprints/HideReelsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/fingerprints/HideReelsFingerprint.kt deleted file mode 100644 index 986c215..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/fingerprints/HideReelsFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.layout.reels.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("hide-reels-fingerprint") -@HideReelsCompatibility -@Version("0.0.1") -object HideReelsFingerprint : MethodFingerprint( - access = AccessFlags.PROTECTED or AccessFlags.FINAL, parameters = listOf("L", "L"), - strings = listOf("multiReelDismissalCallback", "reelItemRenderers", "reelDismissalInfo") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt deleted file mode 100644 index 8ffba77..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/reels/patch/HideReelsPatch.kt +++ /dev/null @@ -1,51 +0,0 @@ -package app.revanced.patches.youtube.layout.reels.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.reels.annotations.HideReelsCompatibility -import app.revanced.patches.youtube.layout.reels.fingerprints.HideReelsFingerprint -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -//@Patch TODO: this is currently in the general-bytecode-ads patch due to the integrations having a preference for including reels or not. Move it here. -@Name("hide-reels") -@Description("Hides reels on the home page.") -@DependsOn([SettingsPatch::class]) -@HideReelsCompatibility -@Version("0.0.1") -class HideReelsPatch : BytecodePatch( - listOf( - HideReelsFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_reel_button_enabled", - StringResource("revanced_reel_button_enabled_title", "Show reels button"), - false, - StringResource("revanced_reel_button_summary_on", "Reels button is shown"), - StringResource("revanced_reel_button_summary_off", "Reels button is hidden") - ) - ) - - val result = HideReelsFingerprint.result!! - - // HideReel will hide the reel view before it is being used, - // so we pass the view to the HideReel method - result.mutableMethod.addInstruction( - result.scanResult.patternScanResult!!.endIndex, - "invoke-static { v2 }, Lapp/revanced/integrations/patches/HideReelsPatch;->HideReel(Landroid/view/View;)V" - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt deleted file mode 100644 index 08f4faa..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/annotations/ReturnYouTubeDislikeCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ReturnYouTubeDislikeCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt deleted file mode 100644 index df1bf11..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/DislikeFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("dislike-fingerprint") -@ReturnYouTubeDislikeCompatibility -@Version("0.0.2") -object DislikeFingerprint : MethodFingerprint( - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - strings = listOf("like/dislike") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt deleted file mode 100644 index f4e794e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/LikeFingerprint.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("like-fingerprint") -@FuzzyPatternScanMethod(2) -@ReturnYouTubeDislikeCompatibility -@Version("0.0.2") -object LikeFingerprint : MethodFingerprint( - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - strings = listOf("like/like") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt deleted file mode 100644 index f613c33..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/RemoveLikeFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("remove-like-fingerprint") -@ReturnYouTubeDislikeCompatibility -@Version("0.0.2") -object RemoveLikeFingerprint : MethodFingerprint( - "V", - AccessFlags.PROTECTED or AccessFlags.CONSTRUCTOR, - strings = listOf("like/removelike") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt deleted file mode 100644 index 62f3e89..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility - -@Name("text-component-spec-fingerprint") -@ReturnYouTubeDislikeCompatibility -@Version("0.0.1") -object TextComponentFingerprint : MethodFingerprint( - strings = listOf("com.google.android.apps.youtube.music") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt deleted file mode 100644 index 6149614..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/fingerprints/TextComponentSpecParentFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility - -@Name("text-component-spec-parent-fingerprint") -@ReturnYouTubeDislikeCompatibility -@Version("0.0.1") -object TextComponentSpecParentFingerprint : MethodFingerprint( - strings = listOf("TextComponentSpec: No converter for extension: ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt deleted file mode 100644 index 0cf0e2c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/patch/ReturnYouTubeDislikePatch.kt +++ /dev/null @@ -1,84 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.MethodFingerprintExtensions.name -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility -import app.revanced.patches.youtube.layout.returnyoutubedislike.fingerprints.* -import app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch.ReturnYouTubeDislikeResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch - -@Patch -@DependsOn([IntegrationsPatch::class, VideoIdPatch::class, ReturnYouTubeDislikeResourcePatch::class]) -@Name("return-youtube-dislike") -@Description("Shows the dislike count of videos using the Return YouTube Dislike API.") -@ReturnYouTubeDislikeCompatibility -@Version("0.0.1") -class ReturnYouTubeDislikePatch : BytecodePatch( - listOf( - TextComponentSpecParentFingerprint, LikeFingerprint, DislikeFingerprint, RemoveLikeFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - listOf( - LikeFingerprint.toPatch(Vote.LIKE), - DislikeFingerprint.toPatch(Vote.DISLIKE), - RemoveLikeFingerprint.toPatch(Vote.REMOVE_LIKE) - ).forEach { (fingerprint, vote) -> - with(fingerprint.result ?: return PatchResultError("Failed to find ${fingerprint.name} method.")) { - mutableMethod.addInstructions( - 0, - """ - const/4 v0, ${vote.value} - invoke-static {v0}, Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->sendVote(I)V - """ - ) - } - } - - VideoIdPatch.injectCall("Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->newVideoLoaded(Ljava/lang/String;)V") - - with(TextComponentFingerprint - .also { it.resolve(context, TextComponentSpecParentFingerprint.result!!.classDef) } - .result ?: return PatchResultError("Could not find createComponent method") - ) { - val createComponentMethod = mutableMethod - - val conversionContextParam = 5 - val textRefParam = createComponentMethod.parameters.size - 2 - val insertIndex = scanResult.stringsScanResult!!.matches.first().index - 2 - - createComponentMethod.addInstructions( - insertIndex, - """ - move-object/from16 v7, p$conversionContextParam - move-object/from16 v8, p$textRefParam - invoke-static {v7, v8}, Lapp/revanced/integrations/patches/ReturnYouTubeDislikePatch;->onComponentCreated(Ljava/lang/Object;Ljava/util/concurrent/atomic/AtomicReference;)V - """ - ) - } - return PatchResultSuccess() - } - - private fun MethodFingerprint.toPatch(voteKind: Vote) = VotePatch(this, voteKind) - - private data class VotePatch(val fingerprint: MethodFingerprint, val voteKind: Vote) - - private enum class Vote(val value: Int) { - LIKE(1), - DISLIKE(-1), - REMOVE_LIKE(0) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt deleted file mode 100644 index 79bd00e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/returnyoutubedislike/resource/patch/ReturnYouTubeDislikeResourcePatch.kt +++ /dev/null @@ -1,42 +0,0 @@ -package app.revanced.patches.youtube.layout.returnyoutubedislike.resource.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.returnyoutubedislike.annotations.ReturnYouTubeDislikeCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings - -@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class]) -@Name("return-youtube-dislike-resource-patch") -@Description("Adds the preferences for Return YouTube Dislike.") -@ReturnYouTubeDislikeCompatibility -@Version("0.0.1") -class ReturnYouTubeDislikeResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - val youtubePackage = "com.google.android.youtube" - SettingsPatch.addPreference( - Preference( - StringResource("revanced_ryd_settings_title", "Return YouTube Dislike"), - Preference.Intent( - youtubePackage, - "ryd_settings", - "com.google.android.libraries.social.licenses.LicenseActivity" - ), - StringResource("revanced_ryd_settings_summary", "Settings for Return YouTube Dislike"), - ) - ) - // merge strings - context.mergeStrings("returnyoutubedislike/host/values/strings.xml") - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt deleted file mode 100644 index 4d5297a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/annotations/SponsorBlockCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SponsorBlockCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt deleted file mode 100644 index e4b90d9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/AppendTimeFingerprint.kt +++ /dev/null @@ -1,36 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("append-time-fingerprint") -@SponsorBlockCompatibility -@Version("0.0.1") -object AppendTimeFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("L", "L", "L"), - listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt deleted file mode 100644 index d895e20..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility - -@Name("create-video-player-seekbar-fingerprint") -@SponsorBlockCompatibility -@Version("0.0.1") -object CreateVideoPlayerSeekbarFingerprint : MethodFingerprint( - "V", - strings = listOf("timed_markers_width") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt deleted file mode 100644 index 6a21835..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import org.jf.dexlib2.util.MethodUtil - -@Name("next-gen-watch-layout-fingerprint") - -@SponsorBlockCompatibility -@Version("0.0.1") -object NextGenWatchLayoutFingerprint : MethodFingerprint( - "V", // constructors return void, in favour of speed of matching, this fingerprint has been added - customFingerprint = { methodDef -> MethodUtil.isConstructor(methodDef) && methodDef.parameterTypes.size == 3 && methodDef.definingClass.endsWith("NextGenWatchLayout;") } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt deleted file mode 100644 index fe6de06..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/PlayerOverlaysLayoutInitFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility - -@Name("player-overlays-layout-init-fingerprint") - -@SponsorBlockCompatibility -@Version("0.0.1") -object PlayerOverlaysLayoutInitFingerprint : MethodFingerprint( - - customFingerprint = { methodDef -> methodDef.returnType.endsWith("YouTubePlayerOverlaysLayout;") } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt deleted file mode 100644 index c9bdfff..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/RectangleFieldInvalidatorFingerprint.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.MethodReference - -@Name("rectangle-field-invalidator-fingerprint") -@SponsorBlockCompatibility -@Version("0.0.1") -object RectangleFieldInvalidatorFingerprint : MethodFingerprint( - "V", - customFingerprint = custom@{ methodDef -> - val instructions = methodDef.implementation?.instructions!! - val instructionCount = instructions.count() - - // the method has definitely more than 5 instructions - if (instructionCount < 5) return@custom false - - val referenceInstruction = instructions.elementAt(instructionCount - 2) // the second to last instruction - val reference = ((referenceInstruction as? ReferenceInstruction)?.reference as? MethodReference) - - reference?.parameterTypes?.size == 1 && reference.name == "invalidate" // the reference is the invalidate(..) method - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ShortsPlayerConstructorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ShortsPlayerConstructorFingerprint.kt deleted file mode 100644 index 8058b9b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/ShortsPlayerConstructorFingerprint.kt +++ /dev/null @@ -1,46 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("shorts-player-constructor-fingerprint") -@FuzzyPatternScanMethod(3) -@SponsorBlockCompatibility -@Version("0.0.1") -object ShortsPlayerConstructorFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.CONSTRUCTOR, - opcodes = listOf( - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.MOVE_OBJECT_FROM16, - Opcode.INVOKE_DIRECT_RANGE, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IPUT_OBJECT, - Opcode.IPUT_OBJECT, - Opcode.CONST_4 - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == SponsorBlockResourcePatch.reelButtonGroupResourceId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt deleted file mode 100644 index 3f4f6e4..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt +++ /dev/null @@ -1,289 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.layout.autocaptions.fingerprints.StartVideoInformerFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.* -import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch -import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch -import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.* -import org.jf.dexlib2.iface.instruction.formats.Instruction35c -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference -import org.jf.dexlib2.iface.reference.StringReference - -@Patch -@DependsOn( - dependencies = [ - VideoInformationPatch::class, // updates video information and adds method to seek in video - PlayerControlsBytecodePatch::class, - IntegrationsPatch::class, - SponsorBlockResourcePatch::class, - VideoIdPatch::class - ] -) -@Name("sponsorblock") -@Description("Integrate SponsorBlock.") -@SponsorBlockCompatibility -@Version("0.0.1") -class SponsorBlockBytecodePatch : BytecodePatch( - listOf( - CreateVideoPlayerSeekbarFingerprint, - NextGenWatchLayoutFingerprint, - AppendTimeFingerprint, - PlayerOverlaysLayoutInitFingerprint, - ShortsPlayerConstructorFingerprint, - StartVideoInformerFingerprint - ) -) { - - private companion object { - const val INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/sponsorblock/PlayerController;" - } - - override fun execute(context: BytecodeContext): PatchResult { - /* - Hook the video time methods - */ - with(VideoInformationPatch) { - videoTimeHook( - INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, - "setVideoTime" - ) - highPrecisionTimeHook( - INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, - "setHighPrecisionVideoTime" - ) - } - - /* - Set current video id - */ - VideoIdPatch.injectCall("$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") - - /* - Seekbar drawing - */ - val seekbarSignatureResult = CreateVideoPlayerSeekbarFingerprint.result!! - val seekbarMethod = seekbarSignatureResult.mutableMethod - val seekbarMethodInstructions = seekbarMethod.implementation!!.instructions - - /* - Get the instance of the seekbar rectangle - */ - for ((index, instruction) in seekbarMethodInstructions.withIndex()) { - if (instruction.opcode != Opcode.MOVE_OBJECT_FROM16) continue - seekbarMethod.addInstruction( - index + 1, - "invoke-static {v0}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V" - ) - break - } - - for ((index, instruction) in seekbarMethodInstructions.withIndex()) { - if (instruction.opcode != Opcode.INVOKE_STATIC) continue - - val invokeInstruction = instruction as Instruction35c - if ((invokeInstruction.reference as MethodReference).name != "round") continue - - val insertIndex = index + 2 - - // set the thickness of the segment - seekbarMethod.addInstruction( - insertIndex, - "invoke-static {v${invokeInstruction.registerC}}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V" - ) - break - } - - /* - Set rectangle absolute left and right positions - */ - val drawRectangleInstructions = seekbarMethodInstructions.filter { - it is ReferenceInstruction && (it.reference as? MethodReference)?.name == "drawRect" && it is FiveRegisterInstruction - }.map { // TODO: improve code - seekbarMethodInstructions.indexOf(it) to (it as FiveRegisterInstruction).registerD - } - - val (indexRight, rectangleRightRegister) = drawRectangleInstructions[0] - val (indexLeft, rectangleLeftRegister) = drawRectangleInstructions[3] - - // order of operation is important here due to the code above which has to be improved - // the reason for that is that we get the index, add instructions and then the offset would be wrong - seekbarMethod.addInstruction( - indexLeft + 1, - "invoke-static {v$rectangleLeftRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V" - ) - seekbarMethod.addInstruction( - indexRight + 1, - "invoke-static {v$rectangleRightRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V" - ) - - /* - Draw segment - */ - val drawSegmentInstructionInsertIndex = (seekbarMethodInstructions.size - 1 - 2) - val (canvasInstance, centerY) = (seekbarMethodInstructions[drawSegmentInstructionInsertIndex] as FiveRegisterInstruction).let { - it.registerC to it.registerE - } - seekbarMethod.addInstruction( - drawSegmentInstructionInsertIndex, - "invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V" - ) - - /* - Voting & Shield button - */ - val controlsMethodResult = PlayerControlsBytecodePatch.showPlayerControlsFingerprintResult - - val controlsLayoutStubResourceId = - ResourceMappingResourcePatch.resourceMappings.single { it.type == "id" && it.name == "controls_layout_stub" }.id - val zoomOverlayResourceId = - ResourceMappingResourcePatch.resourceMappings.single { it.type == "id" && it.name == "video_zoom_overlay_stub" }.id - - methods@ for (method in controlsMethodResult.mutableClass.methods) { - val instructions = method.implementation?.instructions!! - instructions@ for ((index, instruction) in instructions.withIndex()) { - // search for method which inflates the controls layout view - if (instruction.opcode != Opcode.CONST) continue@instructions - - when ((instruction as NarrowLiteralInstruction).wideLiteral) { - controlsLayoutStubResourceId -> { - // replace the view with the YouTubeControlsOverlay - val moveResultInstructionIndex = index + 5 - val inflatedViewRegister = - (instructions[moveResultInstructionIndex] as OneRegisterInstruction).registerA - // initialize with the player overlay object - method.addInstructions( - moveResultInstructionIndex + 1, // insert right after moving the view to the register and use that register - """ - invoke-static {v$inflatedViewRegister}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->initialize(Ljava/lang/Object;)V - invoke-static {v$inflatedViewRegister}, Lapp/revanced/integrations/sponsorblock/VotingButton;->initialize(Ljava/lang/Object;)V - """ - ) - } - - zoomOverlayResourceId -> { - val invertVisibilityMethod = - context.toMethodWalker(method).nextMethod(index - 6, true).getMethod() as MutableMethod - // change visibility of the buttons - invertVisibilityMethod.addInstructions( - 0, """ - invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibilityNegatedImmediate(Z)V - invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibilityNegatedImmediate(Z)V - """.trimIndent() - ) - } - } - } - } - - // change visibility of the buttons - PlayerControlsBytecodePatch.injectVisibilityCheckCall("Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibility(Z)V") - PlayerControlsBytecodePatch.injectVisibilityCheckCall("Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibility(Z)V") - - // set SegmentHelperLayout.context to the player layout instance - val instanceRegister = 0 - NextGenWatchLayoutFingerprint.result!!.mutableMethod.addInstruction( - 3, // after super call - "invoke-static/range {p$instanceRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->addSkipSponsorView15(Landroid/view/View;)V" - ) - - // append the new time to the player layout - val appendTimeFingerprintResult = AppendTimeFingerprint.result!! - val appendTimePatternScanStartIndex = appendTimeFingerprintResult.scanResult.patternScanResult!!.startIndex - val targetRegister = - (appendTimeFingerprintResult.method.implementation!!.instructions.elementAt(appendTimePatternScanStartIndex + 1) as OneRegisterInstruction).registerA - - appendTimeFingerprintResult.mutableMethod.addInstructions( - appendTimePatternScanStartIndex + 2, """ - invoke-static {v$targetRegister}, Lapp/revanced/integrations/sponsorblock/SponsorBlockUtils;->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$targetRegister - """ - ) - - // initialize the player controller - VideoInformationPatch.onCreateHook(INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, "initialize") - - // initialize the sponsorblock view - PlayerOverlaysLayoutInitFingerprint.result!!.mutableMethod.addInstruction( - 6, // after inflating the view - "invoke-static {p0}, Lapp/revanced/integrations/sponsorblock/player/ui/SponsorBlockView;->initialize(Ljava/lang/Object;)V" - ) - - // get rectangle field name - RectangleFieldInvalidatorFingerprint.resolve(context, seekbarSignatureResult.classDef) - val rectangleFieldInvalidatorInstructions = - RectangleFieldInvalidatorFingerprint.result!!.method.implementation!!.instructions - val rectangleFieldName = - ((rectangleFieldInvalidatorInstructions.elementAt(rectangleFieldInvalidatorInstructions.count() - 3) as ReferenceInstruction).reference as FieldReference).name - - // replace the "replaceMeWith*" strings - context - .proxy(context.classes.first { it.type.endsWith("PlayerController;") }) - .mutableClass - .methods - .find { it.name == "setSponsorBarRect" } - ?.let { method -> - fun MutableMethod.replaceStringInstruction(index: Int, instruction: Instruction, with: String) { - val register = (instruction as OneRegisterInstruction).registerA - this.replaceInstruction( - index, "const-string v$register, \"$with\"" - ) - } - for ((index, it) in method.implementation!!.instructions.withIndex()) { - if (it.opcode.ordinal != Opcode.CONST_STRING.ordinal) continue - - when (((it as ReferenceInstruction).reference as StringReference).string) { - "replaceMeWithsetSponsorBarRect" -> - method.replaceStringInstruction(index, it, rectangleFieldName) - - "replaceMeWithsetMillisecondMethod" -> - method.replaceStringInstruction(index, it, "seekHelper") - } - } - } ?: return PatchResultError("Could not find the method which contains the replaceMeWith* strings") - - val startVideoInformerMethod = StartVideoInformerFingerprint.result!!.mutableMethod - startVideoInformerMethod.addInstructions( - 0, """ - const/4 v0, 0x0 - sput-boolean v0, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->shorts_playing:Z - """ - ) - - val shortsPlayerConstructorMethod = ShortsPlayerConstructorFingerprint.result!!.mutableMethod - - shortsPlayerConstructorMethod.addInstructions( - 0, """ - const/4 v0, 0x1 - sput-boolean v0, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->shorts_playing:Z - """ - ) - - // TODO: isSBChannelWhitelisting implementation - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt deleted file mode 100644 index 425bee6..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/resource/patch/SponsorBlockResourcePatch.kt +++ /dev/null @@ -1,116 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.util.resources.ResourceUtils -import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings -import app.revanced.util.resources.ResourceUtils.copyResources -import app.revanced.util.resources.ResourceUtils.copyXmlNode - -@Name("sponsorblock-resource-patch") -@SponsorBlockCompatibility -@DependsOn([FixLocaleConfigErrorPatch::class, SettingsPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class SponsorBlockResourcePatch : ResourcePatch { - companion object { - internal var reelButtonGroupResourceId: Long = 0 - } - - override fun execute(context: ResourceContext): PatchResult { - val youtubePackage = "com.google.android.youtube" - SettingsPatch.addPreference( - Preference( - StringResource("sb_settings", "SponsorBlock"), - Preference.Intent( - youtubePackage, - "sponsorblock_settings", - "com.google.android.libraries.social.licenses.LicenseActivity" - ), - StringResource("revanced_sponsorblock_settings_summary", "SponsorBlock related settings"), - ) - ) - val classLoader = this.javaClass.classLoader - - /* - merge SponsorBlock strings to main strings - */ - context.mergeStrings("sponsorblock/host/values/strings.xml") - - /* - merge SponsorBlock drawables to main drawables - */ - - arrayOf( - ResourceUtils.ResourceGroup( - "layout", - "inline_sponsor_overlay.xml", - "new_segment.xml", - "skip_sponsor_button.xml" - ), - ResourceUtils.ResourceGroup( - // required resource for back button, because when the base APK is used, this resource will not exist - "drawable", - "ic_sb_adjust.xml", - "ic_sb_compare.xml", - "ic_sb_edit.xml", - "ic_sb_logo.xml", - "ic_sb_publish.xml", - "ic_sb_voting.xml" - ), - ResourceUtils.ResourceGroup( - // required resource for back button, because when the base APK is used, this resource will not exist - "drawable-xxxhdpi", "quantum_ic_skip_next_white_24.png" - ) - ).forEach { resourceGroup -> - context.copyResources("sponsorblock", resourceGroup) - } - - /* - merge xml nodes from the host to their real xml files - */ - - // copy nodes from host resources to their real xml files - val hostingResourceStream = - classLoader.getResourceAsStream("sponsorblock/host/layout/youtube_controls_layout.xml")!! - - val targetXmlEditor = context.xmlEditor["res/layout/youtube_controls_layout.xml"] - "RelativeLayout".copyXmlNode( - context.xmlEditor[hostingResourceStream], - targetXmlEditor - ).also { - val children = targetXmlEditor.file.getElementsByTagName("RelativeLayout").item(0).childNodes - - // Replace the startOf with the voting button view so that the button does not overlap - for (i in 1 until children.length) { - val view = children.item(i) - - // Replace the attribute for a specific node only - if (!(view.hasAttributes() && view.attributes.getNamedItem("android:id").nodeValue.endsWith("live_chat_overlay_button"))) continue - - // voting button id from the voting button view from the youtube_controls_layout.xml host file - val votingButtonId = "@+id/voting_button" - - view.attributes.getNamedItem("android:layout_toStartOf").nodeValue = votingButtonId - - break - } - }.close() // close afterwards - - reelButtonGroupResourceId = ResourceMappingResourcePatch.resourceMappings.single { - it.type == "id" && it.name == "reel_persistent_edu_button_group" - }.id - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt deleted file mode 100644 index 5ceff3c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/annotations/StartupShortsResetCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.startupshortsreset.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class StartupShortsResetCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint.kt deleted file mode 100644 index a90a038..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/fingerprints/UserWasInShortsFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.youtube.layout.startupshortsreset.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.startupshortsreset.annotations.StartupShortsResetCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("user-was-in-shorts-fingerprint") -@FuzzyPatternScanMethod(3) -@StartupShortsResetCompatibility -@Version("0.0.1") -object UserWasInShortsFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), - opcodes = listOf( - Opcode.IGET_OBJECT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT, - ), - strings = listOf("Failed to read user_was_in_shorts proto after successful warmup"), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt deleted file mode 100644 index 0398cca..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/startupshortsreset/patch/DisableShortsOnStartupPatch.kt +++ /dev/null @@ -1,59 +0,0 @@ -package app.revanced.patches.youtube.layout.startupshortsreset.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.startupshortsreset.annotations.StartupShortsResetCompatibility -import app.revanced.patches.youtube.layout.startupshortsreset.fingerprints.UserWasInShortsFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("disable-startup-shorts-player") -@Description("Disables playing YouTube Shorts when launching YouTube.") -@StartupShortsResetCompatibility -@Version("0.0.1") -class DisableShortsOnStartupPatch : BytecodePatch( - listOf( - UserWasInShortsFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_startup_shorts_player_enabled", - StringResource("revanced_startup_shorts_player_title", "Disable shorts player at app startup"), - false, - StringResource("revanced_startup_shorts_player_summary_on", "Shorts player is disabled at app startup"), - StringResource("revanced_startup_shorts_player_summary_off", "Shorts player is enabled at app startup") - ) - ) - - val userWasInShortsResult = UserWasInShortsFingerprint.result!! - val userWasInShortsMethod = userWasInShortsResult.mutableMethod - val moveResultIndex = userWasInShortsResult.scanResult.patternScanResult!!.endIndex - - userWasInShortsMethod.addInstructions( - moveResultIndex + 1, """ - invoke-static { }, Lapp/revanced/integrations/patches/DisableStartupShortsPlayerPatch;->disableStartupShortsPlayer()Z - move-result v5 - if-eqz v5, :disable_shorts_player - return-void - :disable_shorts_player - nop - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt deleted file mode 100644 index cb8ed71..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/annotations/TabletMiniPlayerCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.tabletminiplayer.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class TabletMiniPlayerCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt deleted file mode 100644 index 3529cdc..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerDimensionsCalculatorFingerprint.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("mini-player-dimensions-calculator-fingerprint") -@FuzzyPatternScanMethod(2) // TODO: Find a good threshold value -@TabletMiniPlayerCompatibility -@Version("0.0.1") -object MiniPlayerDimensionsCalculatorFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("L"), - listOf( - Opcode.INVOKE_DIRECT, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.FLOAT_TO_DOUBLE, - Opcode.CONST_WIDE_HIGH16, - Opcode.CMPL_DOUBLE, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt deleted file mode 100644 index 4dabce9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("mini-player-override-fingerprint") -@TabletMiniPlayerCompatibility -@Version("0.0.1") -object MiniPlayerOverrideFingerprint : MethodFingerprint( - "Z", AccessFlags.STATIC or AccessFlags.PUBLIC, - opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideNoContextFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideNoContextFingerprint.kt deleted file mode 100644 index 055a047..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerOverrideNoContextFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("mini-player-override-no-context-fingerprint") -@TabletMiniPlayerCompatibility -@Version("0.0.1") -object MiniPlayerOverrideNoContextFingerprint : MethodFingerprint( - "Z", AccessFlags.FINAL or AccessFlags.PRIVATE, - opcodes = listOf(Opcode.RETURN), // anchor to insert the instruction -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerResponseModelSizeCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerResponseModelSizeCheckFingerprint.kt deleted file mode 100644 index afec65f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/fingerprints/MiniPlayerResponseModelSizeCheckFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("mini-player-response-model-size-check-fingerprint") -@TabletMiniPlayerCompatibility -@Version("0.0.1") -object MiniPlayerResponseModelSizeCheckFingerprint : MethodFingerprint( - "L", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("L", "L"), - listOf( - Opcode.RETURN_OBJECT, - Opcode.CHECK_CAST, - Opcode.CHECK_CAST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt deleted file mode 100644 index ffb4948..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/tabletminiplayer/patch/TabletMiniPlayerPatch.kt +++ /dev/null @@ -1,105 +0,0 @@ -package app.revanced.patches.youtube.layout.tabletminiplayer.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.layout.tabletminiplayer.annotations.TabletMiniPlayerCompatibility -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerDimensionsCalculatorFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerOverrideNoContextFingerprint -import app.revanced.patches.youtube.layout.tabletminiplayer.fingerprints.MiniPlayerResponseModelSizeCheckFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("tablet-mini-player") -@Description("Enables the tablet mini player layout.") -@TabletMiniPlayerCompatibility -@Version("0.0.1") -class TabletMiniPlayerPatch : BytecodePatch( - listOf( - MiniPlayerDimensionsCalculatorFingerprint, - MiniPlayerResponseModelSizeCheckFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_tablet_miniplayer", - StringResource("revanced_tablet_miniplayer_title", "Enable the tablet Mini-player"), - false, - StringResource("revanced_tablet_miniplayer_summary_on", "Tablet Mini-player is enabled"), - StringResource("revanced_tablet_miniplayer_summary_off", "Tablet Mini-player is disabled") - ) - ) - - // first resolve the fingerprints via the parent fingerprint - val miniPlayerClass = MiniPlayerDimensionsCalculatorFingerprint.result!!.classDef - - /* - * no context parameter method - */ - MiniPlayerOverrideNoContextFingerprint.resolve(context, miniPlayerClass) - val (method, _, parameterRegister) = MiniPlayerOverrideNoContextFingerprint.addProxyCall() - // - 1 means to insert before the return instruction - val secondInsertIndex = method.implementation!!.instructions.size - 1 - method.insertOverride(secondInsertIndex, parameterRegister /** same register used to return **/) - - /* - * method with context parameter - */ - MiniPlayerOverrideFingerprint.resolve(context, miniPlayerClass) - val (_, _, _) = MiniPlayerOverrideFingerprint.addProxyCall() - - /* - * size check return value override - */ - val (_, _, _) = MiniPlayerResponseModelSizeCheckFingerprint.addProxyCall() - - return PatchResultSuccess() - } - - // helper methods - private companion object { - fun MethodFingerprint.addProxyCall(): Triple { - val (method, scanIndex, parameterRegister) = this.unwrap() - method.insertOverride(scanIndex, parameterRegister) - - return Triple(method, scanIndex, parameterRegister) - } - - fun MutableMethod.insertOverride(index: Int, overrideRegister: Int) { - this.addInstructions( - index, - """ - invoke-static {v$overrideRegister}, Lapp/revanced/integrations/patches/TabletMiniPlayerOverridePatch;->getTabletMiniPlayerOverride(Z)Z - move-result v$overrideRegister - """ - ) - } - - fun MethodFingerprint.unwrap(): Triple { - val result = this.result!! - val scanIndex = result.scanResult.patternScanResult!!.endIndex - val method = result.mutableMethod - val instructions = method.implementation!!.instructions - val parameterRegister = (instructions[scanIndex] as OneRegisterInstruction).registerA - - return Triple(method, scanIndex, parameterRegister) - } - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt deleted file mode 100644 index 5bf3350..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/annotations/ThemeCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.layout.theme.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ThemeCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt deleted file mode 100644 index fc48bbb..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/fingerprints/LithoThemeFingerprint.kt +++ /dev/null @@ -1,32 +0,0 @@ -package app.revanced.patches.youtube.layout.theme.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("litho-ui-fingerprint") -@ThemeCompatibility -@Version("0.0.1") -object LithoThemeFingerprint : MethodFingerprint( - "V", AccessFlags.PROTECTED or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.APUT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_DIRECT, - Opcode.IGET_OBJECT, - Opcode.SGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - Opcode.IGET, - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_NEZ, - Opcode.IGET_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/LithoThemePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/LithoThemePatch.kt deleted file mode 100644 index 4e91d15..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/LithoThemePatch.kt +++ /dev/null @@ -1,38 +0,0 @@ -package app.revanced.patches.youtube.layout.theme.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility -import app.revanced.patches.youtube.layout.theme.fingerprints.LithoThemeFingerprint - -@Name("litho-components-theme") -@Description("Applies a custom theme to litho components.") -@ThemeCompatibility -@Version("0.0.1") -class LithoThemePatch : BytecodePatch( - listOf( - LithoThemeFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - val result = LithoThemeFingerprint.result!! - val method = result.mutableMethod - val patchIndex = result.scanResult.patternScanResult!!.endIndex - 1 - - method.addInstructions( - patchIndex, """ - invoke-static {p1}, Lapp/revanced/integrations/patches/LithoThemePatch;->applyLithoTheme(I)I - move-result p1 - """ - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt deleted file mode 100644 index 434b675..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/theme/patch/ThemePatch.kt +++ /dev/null @@ -1,74 +0,0 @@ -package app.revanced.patches.youtube.layout.theme.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.theme.annotations.ThemeCompatibility -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.util.resources.ResourceUtils -import app.revanced.util.resources.ResourceUtils.copyResources -import org.w3c.dom.Element - -@Patch -@DependsOn([LithoThemePatch::class, FixLocaleConfigErrorPatch::class]) -@Name("theme") -@Description("Applies a custom theme.") -@ThemeCompatibility -@Version("0.0.1") -class ThemePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - val darkThemeBackgroundColor = darkThemeBackgroundColor!! - val lightThemeBackgroundColor = lightThemeBackgroundColor!! - - context.xmlEditor["res/values/colors.xml"].use { editor -> - val resourcesNode = editor.file.getElementsByTagName("resources").item(0) as Element - - for (i in 0 until resourcesNode.childNodes.length) { - val node = resourcesNode.childNodes.item(i) as? Element ?: continue - - node.textContent = when (node.getAttribute("name")) { - "yt_black0", "yt_black1", "yt_black1_opacity95", "yt_black1_opacity98", "yt_black2", "yt_black3", - "yt_black4", "yt_status_bar_background_dark", "material_grey_100", "material_grey_50", - "material_grey_600", "material_grey_800", "material_grey_850", "material_grey_900", - "material_grey_white_1000", "sud_glif_v3_dialog_background_color_dark" -> darkThemeBackgroundColor - - "yt_white1", "yt_white1_opacity95", "yt_white1_opacity98", "yt_white2", "yt_white3", "yt_white4", - "sud_glif_v3_dialog_background_color_light" -> lightThemeBackgroundColor - - else -> continue - } - } - } - - // copies the resource file to change the splash screen color - context.copyResources("theme", - ResourceUtils.ResourceGroup("values-night-v31", "styles.xml") - ) - - return PatchResultSuccess() - } - - companion object : OptionsContainer() { - var darkThemeBackgroundColor: String? by option( - PatchOption.StringOption( - key = "darkThemeBackgroundColor", - default = "@android:color/black", - title = "Background color for the dark theme", - description = "The background color of the dark theme. Can be a hex color or a resource reference.", - ) - ) - - var lightThemeBackgroundColor: String? by option( - PatchOption.StringOption( - key = "lightThemeBackgroundColor", - default = "@android:color/white", - title = "Background color for the light theme", - description = "The background color of the light theme. Can be a hex color or a resource reference.", - ) - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/annotations/WatchinVRCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/annotations/WatchinVRCompatibility.kt deleted file mode 100644 index a4db660..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/annotations/WatchinVRCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.watchinvr.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class WatchinVRCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/fingerprints/WatchinVRFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/fingerprints/WatchinVRFingerprint.kt deleted file mode 100644 index 111d6a7..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/fingerprints/WatchinVRFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.layout.watchinvr.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.watchinvr.annotations.WatchinVRCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("watch-in-vr-fingerprint") -@WatchinVRCompatibility -@Version("0.0.1") -object WatchinVRFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("Z"), - strings = listOf("menu_item_cardboard_vr") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/patch/WatchinVRPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/patch/WatchinVRPatch.kt deleted file mode 100644 index 73e4f54..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watchinvr/patch/WatchinVRPatch.kt +++ /dev/null @@ -1,55 +0,0 @@ -package app.revanced.patches.youtube.layout.watchinvr.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.watchinvr.annotations.WatchinVRCompatibility -import app.revanced.patches.youtube.layout.watchinvr.fingerprints.WatchinVRFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("hide-watch-in-vr") -@Description("Hides the Watch in VR option from the player settings flyout panel.") -@WatchinVRCompatibility -@Version("0.0.1") -class WatchinVRPatch : BytecodePatch( - listOf( - WatchinVRFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_hide_watch_in_vr", - StringResource("revanced_hide_watch_in_vr_title", "Hide Watch in VR option"), - false, - StringResource("revanced_hide_watch_in_vr_summary_on", "Watch in VR option is hidden"), - StringResource("revanced_hide_watch_in_vr_summary_off", "Watch in VR option is shown") - ) - ) - - WatchinVRFingerprint.result!!.mutableMethod.addInstructions( - 0, """ - invoke-static {}, Lapp/revanced/integrations/patches/HideWatchinVRPatch;->hideWatchinVR()Z - move-result v0 - if-eqz v0, :shown - return-void - :shown - nop - """ - ) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/annotations/HideWaterwarkCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/annotations/HideWaterwarkCompatibility.kt deleted file mode 100644 index bd6e356..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/annotations/HideWaterwarkCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.watermark.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HideWatermarkCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkFingerprint.kt deleted file mode 100644 index b880c49..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.layout.watermark.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.watermark.annotations.HideWatermarkCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("hide-watermark-signature") -@HideWatermarkCompatibility -@Version("0.0.1") -object HideWatermarkFingerprint : MethodFingerprint ( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkParentFingerprint.kt deleted file mode 100644 index 7cc41e5..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/fingerprints/HideWatermarkParentFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.layout.watermark.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.watermark.annotations.HideWatermarkCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("hide-watermark-parent-signature") -@HideWatermarkCompatibility -@Version("0.0.1") -object HideWatermarkParentFingerprint : MethodFingerprint ( - "L", AccessFlags.PUBLIC or AccessFlags.FINAL, strings = listOf("player_overlay_in_video_programming") -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/patch/HideWatermarkPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/patch/HideWatermarkPatch.kt deleted file mode 100644 index 4009355..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/watermark/patch/HideWatermarkPatch.kt +++ /dev/null @@ -1,63 +0,0 @@ -package app.revanced.patches.youtube.layout.watermark.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.layout.watermark.annotations.HideWatermarkCompatibility -import app.revanced.patches.youtube.layout.watermark.fingerprints.HideWatermarkFingerprint -import app.revanced.patches.youtube.layout.watermark.fingerprints.HideWatermarkParentFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("hide-watermark") -@Description("Hides creator's watermarks on videos.") -@HideWatermarkCompatibility -@Version("0.0.1") -class HideWatermarkPatch : BytecodePatch( - listOf( - HideWatermarkParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_branding_watermark_enabled", - StringResource("revanced_branding_watermark_enabled_title", "Show branding watermark"), - false, - StringResource("revanced_branding_watermark_summary_on", "Branding watermark is shown"), - StringResource("revanced_branding_watermark_summary_off", "Branding watermark is hidden") - ) - ) - - HideWatermarkFingerprint.resolve(context, HideWatermarkParentFingerprint.result!!.classDef) - val result = HideWatermarkFingerprint.result - ?: return PatchResultError("Required parent method could not be found.") - - val method = result.mutableMethod - val line = method.implementation!!.instructions.size - 5 - - method.removeInstruction(line) - method.addInstructions( - line, """ - invoke-static {}, Lapp/revanced/integrations/patches/BrandingWaterMarkPatch;->isBrandingWatermarkShown()Z - move-result p2 - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/annotations/WideSearchbarCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/annotations/WideSearchbarCompatibility.kt deleted file mode 100644 index b70a46e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/annotations/WideSearchbarCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.layout.widesearchbar.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class WideSearchbarCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneFingerprint.kt deleted file mode 100644 index 0a8547e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.layout.widesearchbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("wide-searchbar-methodone-fingerprint") -@WideSearchbarCompatibility -@Version("0.0.1") -object WideSearchbarOneFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L", "L"), - listOf(Opcode.IF_NEZ, Opcode.SGET_OBJECT, Opcode.IGET_OBJECT, Opcode.INVOKE_STATIC) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneParentFingerprint.kt deleted file mode 100644 index 12db3e5..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarOneParentFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.layout.widesearchbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("wide-searchbar-methodone-parent-fingerprint") -@WideSearchbarCompatibility -@Version("0.0.1") -object WideSearchbarOneParentFingerprint : MethodFingerprint( - "V", AccessFlags.PRIVATE or AccessFlags.FINAL, listOf("L"), - strings = listOf("FEhistory", "FEmy_videos", "FEpurchases") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoFingerprint.kt deleted file mode 100644 index 9a2b912..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoFingerprint.kt +++ /dev/null @@ -1,19 +0,0 @@ -package app.revanced.patches.youtube.layout.widesearchbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("wide-searchbar-methodtwo-fingerprint") -@WideSearchbarCompatibility -@Version("0.0.1") -object WideSearchbarTwoFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, opcodes = listOf( - Opcode.INVOKE_STATIC, Opcode.MOVE_RESULT, Opcode.IF_EQZ, Opcode.NEW_INSTANCE - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoParentFingerprint.kt deleted file mode 100644 index bcd1ba0..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/fingerprints/WideSearchbarTwoParentFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.layout.widesearchbar.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("wide-searchbar-methodtwo-parent-fingerprint") -@WideSearchbarCompatibility -@Version("0.0.1") -object WideSearchbarTwoParentFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), - strings = listOf("VIDEO_QUALITIES_QUICK_MENU_BOTTOM_SHEET_FRAGMENT") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/patch/WideSearchbarPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/patch/WideSearchbarPatch.kt deleted file mode 100644 index 20b1e5c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/widesearchbar/patch/WideSearchbarPatch.kt +++ /dev/null @@ -1,120 +0,0 @@ -package app.revanced.patches.youtube.layout.widesearchbar.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.layout.widesearchbar.annotations.WideSearchbarCompatibility -import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarOneFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarOneParentFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoFingerprint -import app.revanced.patches.youtube.layout.widesearchbar.fingerprints.WideSearchbarTwoParentFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("enable-wide-searchbar") -@Description("Replaces the search icon with a wide search bar. This will hide the YouTube logo when active.") -@WideSearchbarCompatibility -@Version("0.0.1") -class WideSearchbarPatch : BytecodePatch( - listOf( - WideSearchbarOneParentFingerprint, WideSearchbarTwoParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.LAYOUT.addPreferences( - SwitchPreference( - "revanced_wide_searchbar", - StringResource("revanced_wide_searchbar_enabled_title", "Enable wide search bar"), - false, - StringResource("revanced_wide_searchbar_summary_on", "Wide search bar is enabled"), - StringResource("revanced_wide_searchbar_summary_off", "Wide search bar is disabled") - ) - ) - - WideSearchbarOneFingerprint.resolve(context, WideSearchbarOneParentFingerprint.result!!.classDef) - WideSearchbarTwoFingerprint.resolve(context, WideSearchbarTwoParentFingerprint.result!!.classDef) - - val resultOne = WideSearchbarOneFingerprint.result - - //This should be the method aF in class fbn - val targetMethodOne = - context.toMethodWalker(resultOne!!.method) - .nextMethod(resultOne.scanResult.patternScanResult!!.endIndex, true).getMethod() as MutableMethod - - //Since both methods have the same smali code, inject instructions using a method. - addInstructions(targetMethodOne) - - val resultTwo = WideSearchbarTwoFingerprint.result - - //This should be the method aB in class fbn - val targetMethodTwo = - context.toMethodWalker(resultTwo!!.method) - .nextMethod(resultTwo.scanResult.patternScanResult!!.startIndex, true).getMethod() as MutableMethod - - //Since both methods have the same smali code, inject instructions using a method. - addInstructions(targetMethodTwo) - - return PatchResultSuccess() - } - - private fun addInstructions(method: MutableMethod) { - val index = method.implementation!!.instructions.size - 1 - method.addInstructions( - index, """ - invoke-static {}, Lapp/revanced/integrations/patches/NewActionbarPatch;->getNewActionBar()Z - move-result p0 - """ - ) - } - - //targetMethodOne: in class fbn - /* - .method public static aF(Ltxm;)Z - invoke-virtual {p0}, Ltxm;->b()Lahah; - move-result-object p0 - iget-object p0, p0, Lahah;->e:Lakfd; - if-nez p0, :cond_a - sget-object p0, Lakfd;->a:Lakfd; - :cond_a - iget-boolean p0, p0, Lakfd;->V:Z - //added code here: - invoke-static {}, app/revanced/integrations/patches/NewActionbarPatch;->getNewActionBar()Z - move-result p0 - //original code here: - return p0 - .end method - */ - - //targetMethodTwo: in class fbn - /* - .method public static aB(Ltxm;)Z - invoke-virtual {p0}, Ltxm;->b()Lahah; - move-result-object p0 - iget-object p0, p0, Lahah;->e:Lakfd; - if-nez p0, :cond_a - sget-object p0, Lakfd;->a:Lakfd; - :cond_a - iget-boolean p0, p0, Lakfd;->y:Z - //added code here: - invoke-static {}, app/revanced/integrations/patches/NewActionbarPatch;->getNewActionBar()Z - move-result p0 - //original code here: - return p0 - .end method - - */ -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt deleted file mode 100644 index 583e07c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/annotations/AutoRepeatCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.autorepeat.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class AutoRepeatCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt deleted file mode 100644 index c5208c9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.autorepeat.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("auto-repeat-fingerprint") -@AutoRepeatCompatibility -@Version("0.0.1") -object AutoRepeatFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf(), - customFingerprint = { methodDef -> methodDef.implementation!!.instructions.count() == 3 && methodDef.annotations.isEmpty()} -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatParentFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatParentFingerprint.kt deleted file mode 100644 index 9f12136..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/fingerprints/AutoRepeatParentFingerprint.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.youtube.misc.autorepeat.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("auto-repeat-parent-fingerprint") -@AutoRepeatCompatibility -@Version("0.0.1") -object AutoRepeatParentFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - strings = listOf( - "play() called when the player wasn't loaded.", - "play() blocked because Background Playability failed" - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt deleted file mode 100644 index 7de04e2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/autorepeat/patch/AutoRepeatPatch.kt +++ /dev/null @@ -1,88 +0,0 @@ -package app.revanced.patches.youtube.misc.autorepeat.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.removeInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.autorepeat.annotations.AutoRepeatCompatibility -import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint -import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference - -@Patch -@DependsOn([IntegrationsPatch::class]) -@Name("always-autorepeat") -@Description("Always repeats the playing video again.") -@AutoRepeatCompatibility -@Version("0.0.1") -class AutoRepeatPatch : BytecodePatch( - listOf( - AutoRepeatParentFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_pref_auto_repeat", - StringResource("revanced_auto_repeat_enabled_title", "Enable auto-repeat"), - false, - StringResource("revanced_auto_repeat_summary_on", "Auto-repeat is enabled"), - StringResource("revanced_auto_repeat_summary_off", "Auto-repeat is disabled") - ) - ) - - //Get Result from the ParentFingerprint which is the playMethod we need to get. - val parentResult = AutoRepeatParentFingerprint.result - ?: return PatchResultError("ParentFingerprint did not resolve.") - - //this one needs to be called when app/revanced/integrations/patches/AutoRepeatPatch;->shouldAutoRepeat() returns true - val playMethod = parentResult.mutableMethod - AutoRepeatFingerprint.resolve(context, parentResult.classDef) - //String is: Laamp;->E()V - val methodToCall = playMethod.definingClass + "->" + playMethod.name + "()V"; - - //This is the method we search for - val result = AutoRepeatFingerprint.result - ?: return PatchResultError("FingerPrint did not resolve.") - val method = result.mutableMethod - - //Instructions to add to the smali code - val instructions = """ - invoke-static {}, Lapp/revanced/integrations/patches/AutoRepeatPatch;->shouldAutoRepeat()Z - move-result v0 - if-eqz v0, :noautorepeat - invoke-virtual {p0}, $methodToCall - :noautorepeat - return-void - """ - - //Get the implementation so we can do a check for null and get instructions size. - val implementation = method.implementation - ?: return PatchResultError("No Method Implementation found!") - - //Since addInstructions needs an index which starts counting at 0 and size starts counting at 1, - //we have to remove 1 to get the latest instruction - val index = implementation.instructions.size - 1 - - - //remove last instruction which is return-void - method.removeInstruction(index) - // Add our own instructions there - method.addInstructions(index, instructions) - - //Everything worked as expected, return Success - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/annotations/ClientSpoofCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/annotations/ClientSpoofCompatibility.kt deleted file mode 100644 index 96a7b5c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/annotations/ClientSpoofCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.clientspoof.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [ - Package("com.google.android.youtube"), - Package("com.vanced.android.youtube") - ] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class ClientSpoofCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt deleted file mode 100644 index 743f640..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/fingerprints/UserAgentHeaderBuilderFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.clientspoof.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.clientspoof.annotations.ClientSpoofCompatibility -import org.jf.dexlib2.Opcode - -@Name("user-agent-header-builder-fingerprint") -@ClientSpoofCompatibility - -@Version("0.0.1") -object UserAgentHeaderBuilderFingerprint : MethodFingerprint( - parameters = listOf("L", "L", "L"), - opcodes = listOf(Opcode.MOVE_RESULT_OBJECT, Opcode.INVOKE_VIRTUAL), - strings = listOf("(Linux; U; Android "), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/patch/ClientSpoofPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/patch/ClientSpoofPatch.kt deleted file mode 100644 index 2a76d78..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/clientspoof/patch/ClientSpoofPatch.kt +++ /dev/null @@ -1,37 +0,0 @@ -package app.revanced.patches.youtube.misc.clientspoof.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.clientspoof.annotations.ClientSpoofCompatibility -import app.revanced.patches.youtube.misc.clientspoof.fingerprints.UserAgentHeaderBuilderFingerprint -import org.jf.dexlib2.iface.instruction.FiveRegisterInstruction - -@Patch -@Name("client-spoof") -@Description("Spoofs the YouTube or Vanced client to prevent playback issues.") -@ClientSpoofCompatibility -@Version("0.0.1") -class ClientSpoofPatch : BytecodePatch( - listOf(UserAgentHeaderBuilderFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - val result = UserAgentHeaderBuilderFingerprint.result!! - val method = result.mutableMethod - - val insertIndex = result.scanResult.patternScanResult!!.endIndex - val packageNameRegister = (method.instruction(insertIndex) as FiveRegisterInstruction).registerD - - val originalPackageName = "com.google.android.youtube" - method.addInstruction(insertIndex, "const-string v$packageNameRegister, \"$originalPackageName\"") - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt deleted file mode 100644 index cac120b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/annotations/DebuggingCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.debugging.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class DebuggingCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt deleted file mode 100644 index c25b37e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/debugging/patch/DebuggingPatch.kt +++ /dev/null @@ -1,60 +0,0 @@ -package app.revanced.patches.youtube.misc.debugging.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.debugging.annotations.DebuggingCompatibility -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.w3c.dom.Element - -@Patch -@Name("debugging") -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Description("Adds debugging options.") -@DebuggingCompatibility -@Version("0.0.1") -class DebuggingPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_debug_enabled", - StringResource("revanced_debug_title", "Debugging"), - false, - StringResource("revanced_debug_on", "Debug logs are enabled"), - StringResource("revanced_debug_off", "Debug logs are disabled") - ) - ) - - if (debuggable == true) { - context.xmlEditor["AndroidManifest.xml"].use { dom -> - val applicationNode = dom - .file - .getElementsByTagName("application") - .item(0) as Element - - // set application as debuggable - applicationNode.setAttribute("android:debuggable", "true") - } - } - - return PatchResultSuccess() - } - - companion object : OptionsContainer() { - var debuggable: Boolean? by option( - PatchOption.BooleanOption( - key = "debuggable", - default = false, - title = "App debugging", - description = "Whether to make the app debuggable on Android.", - ) - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt deleted file mode 100644 index a95e127..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/annotations/HDRBrightnessCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.hdrbrightness.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class HDRBrightnessCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt deleted file mode 100644 index a8f4348..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/fingerprints/HDRBrightnessFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.hdrbrightness.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility -import org.jf.dexlib2.Opcode - -@Name("hdr-brightness-fingerprint") -@HDRBrightnessCompatibility -@Version("0.0.1") -object HDRBrightnessFingerprint : MethodFingerprint( - "V", - opcodes = listOf(Opcode.CMPL_FLOAT), - strings = listOf("c.SettingNotFound;", "screen_brightness", "android.mediaview"), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt deleted file mode 100644 index 24f18d2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/hdrbrightness/patch/HDRBrightnessPatch.kt +++ /dev/null @@ -1,64 +0,0 @@ -package app.revanced.patches.youtube.misc.hdrbrightness.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.hdrbrightness.annotations.HDRBrightnessCompatibility -import app.revanced.patches.youtube.misc.hdrbrightness.fingerprints.HDRBrightnessFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.instruction.TwoRegisterInstruction -import org.jf.dexlib2.iface.reference.FieldReference - -@Patch -@Name("hdr-auto-brightness") -@Description("Makes the brightness of HDR videos follow the system default.") -@HDRBrightnessCompatibility -@Version("0.0.2") -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -class HDRBrightnessPatch : BytecodePatch( - listOf(HDRBrightnessFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_pref_hdr_autobrightness", - StringResource("revanced_hdr_autobrightness_enabled_title", "Enable auto HDR brightness"), - true, - StringResource("revanced_hdr_autobrightness_summary_on", "Auto HDR brightness is enabled"), - StringResource("revanced_hdr_autobrightness_summary_off", "Auto HDR brightness is disabled") - ) - ) - - val method = HDRBrightnessFingerprint.result!!.mutableMethod - - method.implementation!!.instructions.filter { instruction -> - val fieldReference = (instruction as? ReferenceInstruction)?.reference as? FieldReference - fieldReference?.let { it.name == "screenBrightness" } == true - }.forEach { instruction -> - val brightnessRegisterIndex = method.implementation!!.instructions.indexOf(instruction) - val register = (instruction as TwoRegisterInstruction).registerA - - val insertIndex = brightnessRegisterIndex + 1 - method.addInstructions( - insertIndex, - """ - invoke-static {v$register}, Lapp/revanced/integrations/patches/HDRAutoBrightnessPatch;->getHDRBrightness(F)F - move-result v$register - """ - ) - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt deleted file mode 100644 index cff3b4d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/annotations/IntegrationsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.integrations.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class IntegrationsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt deleted file mode 100644 index 66b874d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/InitFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.integrations.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility - -@Name("init-fingerprint") -@IntegrationsCompatibility -@Version("0.0.1") -object InitFingerprint : MethodFingerprint( - strings = listOf("Application creation") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt deleted file mode 100644 index 0d1312b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/ServiceFingerprint.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.integrations.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility - -@Name("service-fingerprint") -@IntegrationsCompatibility -@Version("0.0.1") -object ServiceFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> methodDef.definingClass.endsWith("ApiPlayerService;") && methodDef.name == "" } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt deleted file mode 100644 index 5bd664d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/fingerprints/StandalonePlayerFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.integrations.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility - -@Name("standalone-player-fingerprint") -@IntegrationsCompatibility -@Version("0.0.1") -object StandalonePlayerFingerprint : MethodFingerprint( - strings = listOf( - "Invalid PlaybackStartDescriptor. Returning the instance itself.", - "com.google.android.music", - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt deleted file mode 100644 index f7eaff3..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/integrations/patch/IntegrationsPatch.kt +++ /dev/null @@ -1,59 +0,0 @@ -package app.revanced.patches.youtube.misc.integrations.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.MethodFingerprintExtensions.name -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.or -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patcher.util.smali.toInstructions -import app.revanced.patches.youtube.misc.integrations.annotations.IntegrationsCompatibility -import app.revanced.patches.youtube.misc.integrations.fingerprints.InitFingerprint -import app.revanced.patches.youtube.misc.integrations.fingerprints.ServiceFingerprint -import app.revanced.patches.youtube.misc.integrations.fingerprints.StandalonePlayerFingerprint -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.immutable.ImmutableMethod -import org.jf.dexlib2.immutable.ImmutableMethodImplementation - -@Name("integrations") -@Description("Applies mandatory patches to implement the ReVanced integrations into the application.") -@IntegrationsCompatibility -@Version("0.0.1") -class IntegrationsPatch : BytecodePatch( - listOf( - InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint - ) -) { - companion object { - private const val INTEGRATIONS_DESCRIPTOR = "Lapp/revanced/integrations/utils/ReVancedUtils;" - } - - override fun execute(context: BytecodeContext): PatchResult { - if (context.findClass(INTEGRATIONS_DESCRIPTOR) == null) - return PatchResultError("Integrations have not been merged yet. This patch can not succeed without merging the integrations.") - - arrayOf(InitFingerprint, StandalonePlayerFingerprint, ServiceFingerprint).map { - it to (it.result ?: return PatchResultError("${it.name} failed to resolve")) - }.forEach { (fingerprint, result) -> - with(result.mutableMethod) { - // parameter which holds the context - val contextParameter = if (fingerprint == ServiceFingerprint) parameters.size else 1 - // register which holds the context - val contextRegister = implementation!!.registerCount - contextParameter - - addInstruction( - 0, - "sput-object v$contextRegister, $INTEGRATIONS_DESCRIPTOR->context:Landroid/content/Context;" - ) - } - } - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt deleted file mode 100644 index 5d8541a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/annotation/LithoFilterCompatibility.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.litho.filter.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class LithoFilterCompatibility - diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt deleted file mode 100644 index 10d0fca..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/ComponentContextParserFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.youtube.misc.litho.filter.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility -import org.jf.dexlib2.Opcode - -@Name("component-context-parser-fingerprint") -@LithoFilterCompatibility -@Version("0.0.1") -object ComponentContextParserFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.GOTO, - Opcode.INVOKE_VIRTUAL, - Opcode.CONST_16, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_OBJECT, - Opcode.NEW_INSTANCE - ), - strings = listOf("LoggingProperties are not in proto format") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt deleted file mode 100644 index dc0ef9b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/fingerprints/EmptyComponentBuilderFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.litho.filter.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility -import org.jf.dexlib2.Opcode - -@Name("empty-component-builder-fingerprint") -@LithoFilterCompatibility -@Version("0.0.1") -object EmptyComponentBuilderFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.INVOKE_STATIC_RANGE - ), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt deleted file mode 100644 index 851d39e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/litho/filter/patch/LithoFilterPatch.kt +++ /dev/null @@ -1,86 +0,0 @@ -package app.revanced.patches.youtube.misc.litho.filter.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultError -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.util.smali.ExternalLabel -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.litho.filter.annotation.LithoFilterCompatibility -import app.revanced.patches.youtube.misc.litho.filter.fingerprints.ComponentContextParserFingerprint -import app.revanced.patches.youtube.misc.litho.filter.fingerprints.EmptyComponentBuilderFingerprint -import org.jf.dexlib2.iface.instruction.Instruction -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference - -@DependsOn([IntegrationsPatch::class]) -@Description("Hooks the method which parses the bytes into a ComponentContext to filter components.") -@LithoFilterCompatibility -@Version("0.0.1") -class LithoFilterPatch : BytecodePatch( - listOf(ComponentContextParserFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - ComponentContextParserFingerprint.result?.let { result -> - val builderMethodIndex = EmptyComponentBuilderFingerprint - .also { it.resolve(context, result.mutableMethod, result.mutableClass) } - .let { it.result!!.scanResult.patternScanResult!!.startIndex } - - val emptyComponentFieldIndex = builderMethodIndex + 2 - - with(result.mutableMethod) { - val insertHookIndex = result.scanResult.patternScanResult!!.endIndex - val clobberedRegister = (instruction(insertHookIndex - 3) as OneRegisterInstruction).registerA - - val builderMethodDescriptor = instruction(builderMethodIndex).toDescriptor() - val emptyComponentFieldDescriptor = instruction(emptyComponentFieldIndex).toDescriptor() - - addInstructions( - insertHookIndex, // right after setting the component.pathBuilder field, - """ - invoke-static {v5, v2}, Lapp/revanced/integrations/patches/LithoFilterPatch;->filter(Ljava/lang/StringBuilder;Ljava/lang/String;)Z - move-result v$clobberedRegister - if-eqz v$clobberedRegister, :not_an_ad - move-object/from16 v2, p1 - invoke-static {v2}, $builderMethodDescriptor - move-result-object v0 - iget-object v0, v0, $emptyComponentFieldDescriptor - return-object v0 - """, - listOf(ExternalLabel("not_an_ad", instruction(insertHookIndex))) - ) - } - } ?: return PatchResultError("Could not find the method to hook.") - - return PatchResultSuccess() - } - - private companion object { - fun Instruction.toDescriptor() = when (val reference = (this as ReferenceInstruction).reference) { - MethodReference::class -> { - val methodReference = reference as MethodReference - "${methodReference.definingClass}->${methodReference.name}(${ - methodReference.parameterTypes.joinToString( - "" - ) { it } - })${methodReference.returnType}" - } - - FieldReference::class -> { - val fieldReference = reference as FieldReference - "${fieldReference.definingClass}->${fieldReference.name}:${fieldReference.type}" - } - - else -> throw PatchResultError("Unsupported reference type") - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt deleted file mode 100644 index a304b71..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/annotations/FixLocaleConfigErrorCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.manifest.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class FixLocaleConfigErrorCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt deleted file mode 100644 index 801e444..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/manifest/patch/FixLocaleConfigErrorPatch.kt +++ /dev/null @@ -1,36 +0,0 @@ -package app.revanced.patches.youtube.misc.manifest.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patches.youtube.misc.manifest.annotations.FixLocaleConfigErrorCompatibility -import org.w3c.dom.Element - -@Name("locale-config-fix") -@Description("Fixes an error when building the resources by patching the manifest file.") -@FixLocaleConfigErrorCompatibility -@Version("0.0.1") -class FixLocaleConfigErrorPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - // create an xml editor instance - context.xmlEditor["AndroidManifest.xml"].use { - // edit the application nodes attribute... - val applicationNode = it - .file - .getElementsByTagName("application") - .item(0) as Element - - - // by replacing the attributes name - val attribute = "android:localeConfig" - applicationNode.setAttribute("localeConfig", applicationNode.getAttribute(attribute)) - applicationNode.removeAttribute(attribute) - } - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/mapping/patch/ResourceMappingResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/mapping/patch/ResourceMappingResourcePatch.kt deleted file mode 100644 index 7e08d4b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/mapping/patch/ResourceMappingResourcePatch.kt +++ /dev/null @@ -1,73 +0,0 @@ -package app.revanced.patches.youtube.misc.mapping.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import org.w3c.dom.Element -import java.util.* -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - - -@Name("resource-mapping") -@Description("Creates a map of public resources.") -@Version("0.0.1") -class ResourceMappingResourcePatch : ResourcePatch { - companion object { - internal lateinit var resourceMappings: List - private set - - private val THREAD_COUNT = Runtime.getRuntime().availableProcessors() - private val threadPoolExecutor = Executors.newFixedThreadPool(THREAD_COUNT) - } - - override fun execute(context: ResourceContext): PatchResult { - // save the file in memory to concurrently read from - val resourceXmlFile = context["res/values/public.xml"].readBytes() - - // create a synchronized list to store the resource mappings - val mappings = Collections.synchronizedList(mutableListOf()) - - for (threadIndex in 0 until THREAD_COUNT) { - threadPoolExecutor.execute thread@{ - context.xmlEditor[resourceXmlFile.inputStream()].use { editor -> - val resources = editor.file.documentElement.childNodes - val resourcesLength = resources.length - val jobSize = resourcesLength / THREAD_COUNT - - val batchStart = jobSize * threadIndex - val batchEnd = jobSize * (threadIndex + 1) - element@ for (i in batchStart until batchEnd) { - // make sure to not to go out of bounds when rounding errors occur at calculating the jobSize - if (i >= resourcesLength) return@thread - - val node = resources.item(i) - if (node !is Element) continue - - val nameAttribute = node.getAttribute("name") - val typeAttribute = node.getAttribute("type") - - if (node.nodeName != "public" || nameAttribute.startsWith("APKTOOL")) continue - - val id = node.getAttribute("id").substring(2).toLong(16) - mappings.add(ResourceElement(typeAttribute, nameAttribute, id)) - } - } - } - } - - threadPoolExecutor - .also { it.shutdown() } - .awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS) - - resourceMappings = mappings - - return PatchResultSuccess() - } -} - -data class ResourceElement(val type: String, val name: String, val id: Long) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt deleted file mode 100644 index 0ee4735..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/annotations/MicroGPatchCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MicroGPatchCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt deleted file mode 100644 index 4604055..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastContextFetchFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("cast-context-fetch-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object CastContextFetchFingerprint : MethodFingerprint( - strings = listOf("Error fetching CastContext.") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt deleted file mode 100644 index 22b9b93..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("cast-module-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object CastDynamiteModuleFingerprint : MethodFingerprint( - strings = listOf("com.google.android.gms.cast.framework.internal.CastDynamiteModuleImpl") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt deleted file mode 100644 index a2af640..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/CastDynamiteModuleV2Fingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("cast-context-fetch-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object CastDynamiteModuleV2Fingerprint : MethodFingerprint( - strings = listOf("Failed to load module via V2: ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt deleted file mode 100644 index 58232d6..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/GooglePlayUtilityFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("google-play-utility-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object GooglePlayUtilityFingerprint : MethodFingerprint( - "I", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L", "L"), - strings = listOf("This should never happen.", "MetadataValueReader", "com.google.android.gms") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt deleted file mode 100644 index c57f780..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/IntegrityCheckFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("google-play-sig-check-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object IntegrityCheckFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L"), - strings = listOf("This should never happen.", "GooglePlayServicesUtil", "Google Play Store signature invalid.") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt deleted file mode 100644 index b94fbd2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/PrimeFingerprint.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility - -@Name("google-play-prime-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object PrimeFingerprint : MethodFingerprint( - strings = listOf("com.google.android.GoogleCamera", "com.android.vending") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt deleted file mode 100644 index 4a7908a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/fingerprints/ServiceCheckFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility -import org.jf.dexlib2.AccessFlags - -@Name("google-play-service-checker-fingerprint") -@MicroGPatchCompatibility -@Version("0.0.1") -object ServiceCheckFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "I"), - strings = listOf("Google Play Services not available", "GooglePlayServices not available due to error ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt deleted file mode 100644 index f309d7b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/bytecode/MicroGBytecodePatch.kt +++ /dev/null @@ -1,76 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.patch.bytecode - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.shared.fingerprints.WatchWhileActivityFingerprint -import app.revanced.patches.youtube.layout.castbutton.patch.HideCastButtonPatch -import app.revanced.patches.youtube.misc.clientspoof.patch.ClientSpoofPatch -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility -import app.revanced.patches.youtube.misc.microg.fingerprints.* -import app.revanced.patches.youtube.misc.microg.patch.resource.MicroGResourcePatch -import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME -import app.revanced.util.microg.MicroGBytecodeHelper - -@Patch -@DependsOn( - [ - MicroGResourcePatch::class, - HideCastButtonPatch::class, - ClientSpoofPatch::class - ] -) -@Name("microg-support") -@Description("Allows YouTube ReVanced to run without root and under a different package name with Vanced MicroG.") -@MicroGPatchCompatibility -@Version("0.0.1") -class MicroGBytecodePatch : BytecodePatch( - listOf( - IntegrityCheckFingerprint, - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint, - PrimeFingerprint, - WatchWhileActivityFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - // apply common microG patch - MicroGBytecodeHelper.patchBytecode( - context, arrayOf( - MicroGBytecodeHelper.packageNameTransform( - PACKAGE_NAME, - REVANCED_PACKAGE_NAME - ) - ), - MicroGBytecodeHelper.PrimeMethodTransformationData( - PrimeFingerprint, - PACKAGE_NAME, - REVANCED_PACKAGE_NAME - ), - listOf( - IntegrityCheckFingerprint, - ServiceCheckFingerprint, - GooglePlayUtilityFingerprint, - CastDynamiteModuleFingerprint, - CastDynamiteModuleV2Fingerprint, - CastContextFetchFingerprint - ) - ) - - // inject the notice for MicroG - MicroGBytecodeHelper.injectNotice(WatchWhileActivityFingerprint) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt deleted file mode 100644 index 6d747a4..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/patch/resource/MicroGResourcePatch.kt +++ /dev/null @@ -1,62 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.patch.resource - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.microg.annotations.MicroGPatchCompatibility -import app.revanced.patches.youtube.misc.microg.shared.Constants.PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_APP_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.REVANCED_PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_NAME -import app.revanced.patches.youtube.misc.microg.shared.Constants.SPOOFED_PACKAGE_SIGNATURE -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch -import app.revanced.util.microg.Constants.MICROG_VENDOR -import app.revanced.util.microg.MicroGManifestHelper -import app.revanced.util.microg.MicroGResourceHelper - -@Name("microg-resource-patch") -@DependsOn([FixLocaleConfigErrorPatch::class, SettingsResourcePatch::class]) -@Description("Resource patch to allow YouTube ReVanced to run without root and under a different package name.") -@MicroGPatchCompatibility -@Version("0.0.1") -class MicroGResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.addPreference( - Preference( - StringResource("microg_settings", "MicroG Settings"), - Preference.Intent("$MICROG_VENDOR.android.gms", "", "org.microg.gms.ui.SettingsActivity"), - StringResource("microg_settings_summary", "Settings for MicroG"), - ) - ) - SettingsPatch.renameIntentsTargetPackage(REVANCED_PACKAGE_NAME) - - // update manifest - MicroGResourceHelper.patchManifest( - context, - PACKAGE_NAME, - REVANCED_PACKAGE_NAME, - REVANCED_APP_NAME - ) - - // add metadata to manifest - MicroGManifestHelper.addSpoofingMetadata( - context, - SPOOFED_PACKAGE_NAME, - SPOOFED_PACKAGE_SIGNATURE - ) - - // add strings - MicroGResourceHelper.addStrings(context) - - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt deleted file mode 100644 index 84b48de..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/microg/shared/Constants.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.microg.shared - -object Constants { - internal const val REVANCED_APP_NAME = "YouTube ReVanced" - internal const val REVANCED_PACKAGE_NAME = "app.revanced.android.youtube" - internal const val PACKAGE_NAME = "com.google.android.youtube" - internal const val SPOOFED_PACKAGE_NAME = PACKAGE_NAME - internal const val SPOOFED_PACKAGE_SIGNATURE = "24bb24c05e47e0aefa68a58a766179d9b613a600" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt deleted file mode 100644 index 6521437..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/annotations/MinimizedPlaybackCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.minimizedplayback.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class MinimizedPlaybackCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackKidsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackKidsFingerprint.kt deleted file mode 100644 index 0d5ad05..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackKidsFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("minimized-playback-kids-fingerprint") -@MinimizedPlaybackCompatibility -@Version("0.0.1") -object MinimizedPlaybackKidsFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("I", "L", "L"), - listOf( - Opcode.IF_EQZ, - Opcode.SGET_OBJECT, - Opcode.IF_NE, - Opcode.CONST_4, - Opcode.IPUT_BOOLEAN, - Opcode.IF_EQZ, - Opcode.IGET, - Opcode.INVOKE_STATIC - ), - customFingerprint = { it.definingClass.endsWith("MinimizedPlaybackPolicyController;") } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt deleted file mode 100644 index eca6d9b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackManagerFingerprint.kt +++ /dev/null @@ -1,47 +0,0 @@ -package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("minimized-playback-manager-fingerprint") -@FuzzyPatternScanMethod(2) // FIXME: Test this threshold and find the best value. -@MinimizedPlaybackCompatibility -@Version("0.0.1") -object MinimizedPlaybackManagerFingerprint : MethodFingerprint( - "Z", - AccessFlags.PUBLIC or AccessFlags.STATIC, - listOf("L"), - listOf( - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET, - Opcode.AND_INT_LIT16, - Opcode.IF_EQZ, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.CONST, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.IGET, - Opcode.IF_NE, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.GOTO, - Opcode.SGET_OBJECT, - Opcode.GOTO, - Opcode.CONST_4, - Opcode.IF_EQZ, - Opcode.IGET_BOOLEAN, - Opcode.IF_EQZ - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackSettingsFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackSettingsFingerprint.kt deleted file mode 100644 index 1718432..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/fingerprints/MinimizedPlaybackSettingsFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.misc.minimizedplayback.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("minimized-playback-manager-fingerprint") -@FuzzyPatternScanMethod(2) -@MinimizedPlaybackCompatibility -@Version("0.0.1") -object MinimizedPlaybackSettingsFingerprint : MethodFingerprint( - "L", - AccessFlags.PUBLIC or AccessFlags.FINAL, - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.IF_NEZ, - Opcode.GOTO, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST - ), -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt deleted file mode 100644 index bf3b630..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/minimizedplayback/patch/MinimizedPlaybackPatch.kt +++ /dev/null @@ -1,88 +0,0 @@ -package app.revanced.patches.youtube.misc.minimizedplayback.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.minimizedplayback.annotations.MinimizedPlaybackCompatibility -import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackKidsFingerprint -import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackManagerFingerprint -import app.revanced.patches.youtube.misc.minimizedplayback.fingerprints.MinimizedPlaybackSettingsFingerprint -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.MethodReference - - -@Patch -@Name("minimized-playback") -@Description("Enables minimized and background playback.") -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@MinimizedPlaybackCompatibility -@Version("0.0.1") -class MinimizedPlaybackPatch : BytecodePatch( - listOf( - MinimizedPlaybackKidsFingerprint, MinimizedPlaybackManagerFingerprint, MinimizedPlaybackSettingsFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_enable_minimized_playback", - StringResource("revanced_minimized_playback_enabled_title", "Enable minimized playback"), - true, - StringResource("revanced_minimized_playback_summary_on", "Minimized playback is enabled"), - StringResource("revanced_minimized_playback_summary_off", "Minimized playback is disabled") - ) - ) - - // Instead of removing all instructions like Vanced, - // we return the method at the beginning instead - MinimizedPlaybackManagerFingerprint.result!!.mutableMethod.addInstructions( - 0, """ - invoke-static {}, Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;->isMinimizedPlaybackEnabled()Z - move-result v0 - return v0 - """ - ) - - val method = MinimizedPlaybackSettingsFingerprint.result!!.mutableMethod - val booleanCalls = method.implementation!!.instructions.withIndex() - .filter { ((it.value as? ReferenceInstruction)?.reference as? MethodReference)?.returnType == "Z" } - - val settingsBooleanIndex = booleanCalls.elementAt(1).index - val settingsBooleanMethod = - context.toMethodWalker(method).nextMethod(settingsBooleanIndex, true).getMethod() as MutableMethod - - settingsBooleanMethod.addInstructions( - 0, """ - invoke-static {}, Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;->isMinimizedPlaybackEnabled()Z - move-result v0 - return v0 - """ - ) - - MinimizedPlaybackKidsFingerprint.result!!.mutableMethod.addInstructions( - 0, """ - invoke-static {}, Lapp/revanced/integrations/patches/MinimizedPlaybackPatch;->isMinimizedPlaybackEnabled()Z - move-result v0 - if-eqz v0, :enable - return-void - :enable - nop - """ - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/annotations/OpenLinksDirectlyCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/annotations/OpenLinksDirectlyCompatibility.kt deleted file mode 100644 index d16102a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/annotations/OpenLinksDirectlyCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.openlinksdirectly.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.34.36", "17.36.39", "17.38.36", "17.39.35" , "17.40.41", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class OpenLinksDirectlyCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintPrimary.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintPrimary.kt deleted file mode 100644 index e5c497f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintPrimary.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.youtube.misc.openlinksdirectly.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.openlinksdirectly.annotations.OpenLinksDirectlyCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("open-links-directly-primary-fingerprint") -@OpenLinksDirectlyCompatibility -@Version("0.0.1") -object OpenLinksDirectlyFingerprintPrimary : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.CHECK_CAST, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.RETURN_OBJECT, - Opcode.CHECK_CAST, - Opcode.SGET - ) -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintSecondary.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintSecondary.kt deleted file mode 100644 index 2dda99b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/fingerprints/OpenLinksDirectlyFingerprintSecondary.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.misc.openlinksdirectly.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.openlinksdirectly.annotations.OpenLinksDirectlyCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("open-links-directly-secondary-fingerprint") -@OpenLinksDirectlyCompatibility -@Version("0.0.1") -object OpenLinksDirectlyFingerprintSecondary : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L"), listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.RETURN_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.CONST_STRING - ), - strings = listOf("Uri must have an absolute scheme") -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt deleted file mode 100644 index 38ad89a..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/openlinksdirectly/patch/OpenLinksDirectlyPatch.kt +++ /dev/null @@ -1,72 +0,0 @@ -package app.revanced.patches.youtube.misc.openlinksdirectly.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.openlinksdirectly.annotations.OpenLinksDirectlyCompatibility -import app.revanced.patches.youtube.misc.openlinksdirectly.fingerprints.OpenLinksDirectlyFingerprintPrimary -import app.revanced.patches.youtube.misc.openlinksdirectly.fingerprints.OpenLinksDirectlyFingerprintSecondary -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import org.jf.dexlib2.iface.instruction.Instruction -import org.jf.dexlib2.iface.instruction.formats.Instruction11x -import org.jf.dexlib2.iface.instruction.formats.Instruction35c - -@Patch -@DependsOn([IntegrationsPatch::class, SettingsPatch::class]) -@Name("open-links-directly") -@Description("Bypasses redirect links and allows opening links directly.") -@OpenLinksDirectlyCompatibility -@Version("0.0.1") -class OpenLinksDirectlyPatch : BytecodePatch( - listOf( - OpenLinksDirectlyFingerprintPrimary, OpenLinksDirectlyFingerprintSecondary - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_uri_redirect", - StringResource("revanced_uri_redirect_title", "Open links directly"), - true, - StringResource("revanced_uri_redirect_summary_on", "Enabled"), - StringResource("revanced_uri_redirect_summary_off", "Disabled") - ) - ) - - OpenLinksDirectlyFingerprintPrimary.hookUriParser(true) - OpenLinksDirectlyFingerprintSecondary.hookUriParser(false) - - return PatchResultSuccess() - } -} - -fun MethodFingerprint.hookUriParser(isPrimaryFingerprint: Boolean) { - fun getTargetRegister(instruction: Instruction): Int { - if (isPrimaryFingerprint) return (instruction as Instruction35c).registerC - return (instruction as Instruction11x).registerA - } - with(this.result!!) { - val startIndex = scanResult.patternScanResult!!.startIndex - val instruction = method.implementation!!.instructions.elementAt(startIndex + 1) - val insertIndex = if (isPrimaryFingerprint) 1 else 2 - val targetRegister = getTargetRegister(instruction) - - mutableMethod.addInstructions( - startIndex + insertIndex, """ - invoke-static {v$targetRegister}, Lapp/revanced/integrations/patches/OpenLinksDirectlyPatch;->parseRedirectUri(Ljava/lang/String;)Ljava/lang/String; - move-result-object v$targetRegister - """ - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/annotations/FixPlaybackCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/annotations/FixPlaybackCompatibility.kt deleted file mode 100644 index df111c4..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/annotations/FixPlaybackCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.playback.fix.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.41.37") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class FixPlaybackCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/patch/FixPlaybackPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/patch/FixPlaybackPatch.kt deleted file mode 100644 index 9402fb2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playback/fix/patch/FixPlaybackPatch.kt +++ /dev/null @@ -1,52 +0,0 @@ -package app.revanced.patches.youtube.misc.playback.fix.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.playback.fix.annotations.FixPlaybackCompatibility -import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch - -@DependsOn([ - IntegrationsPatch::class, - VideoInformationPatch::class, // updates video length and adds method to seek in video, necessary for this patch - SettingsPatch::class, - VideoIdPatch::class -]) -@Name("fix-playback") -@Description("Fixes the issue with videos not playing when video ads are removed.") -@FixPlaybackCompatibility -@Version("0.0.1") -class FixPlaybackPatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_fix_playback", - StringResource("revanced_fix_playback_title", "Fix video playback issues"), - false, - StringResource( - "revanced_fix_playback_summary_on", - "The fix is enabled" - ), - StringResource( - "revanced_fix_playback_summary_off", - "The fix is disabled" - ) - ) - ) - - // If a new video loads, fix the playback issue - VideoIdPatch.injectCall("Lapp/revanced/integrations/patches/FixPlaybackPatch;->newVideoLoaded(Ljava/lang/String;)V") - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt deleted file mode 100644 index 72232ac..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/annotation/PlayerControlsCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.playercontrols.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PlayerControlsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt deleted file mode 100644 index d21e6ce..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/bytecode/patch/PlayerControlsBytecodePatch.kt +++ /dev/null @@ -1,83 +0,0 @@ -package app.revanced.patches.youtube.misc.playercontrols.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprintResult -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility -import app.revanced.patches.youtube.misc.playercontrols.fingerprints.BottomControlsInflateFingerprint -import app.revanced.patches.youtube.misc.playercontrols.fingerprints.PlayerControlsVisibilityFingerprint -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Name("player-controls-bytecode-patch") -@DependsOn([ResourceMappingResourcePatch::class]) -@Description("Manages the code for the player controls of the YouTube player.") -@PlayerControlsCompatibility -@Version("0.0.1") -class PlayerControlsBytecodePatch : BytecodePatch( - listOf(PlayerControlsVisibilityFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - showPlayerControlsFingerprintResult = PlayerControlsVisibilityFingerprint.result!! - - bottomUiContainerResourceId = ResourceMappingResourcePatch - .resourceMappings - .single { it.type == "id" && it.name == "bottom_ui_container_stub" }.id - - // TODO: another solution is required, this is hacky - listOf(BottomControlsInflateFingerprint).resolve(context, context.classes) - inflateFingerprintResult = BottomControlsInflateFingerprint.result!! - - return PatchResultSuccess() - } - - internal companion object { - var bottomUiContainerResourceId: Long = 0 - - lateinit var showPlayerControlsFingerprintResult: MethodFingerprintResult - - private var inflateFingerprintResult: MethodFingerprintResult? = null - set(fingerprint) { - field = fingerprint!!.also { - moveToRegisterInstructionIndex = it.scanResult.patternScanResult!!.endIndex - viewRegister = - (it.mutableMethod.implementation!!.instructions[moveToRegisterInstructionIndex] as OneRegisterInstruction).registerA - } - } - - private var moveToRegisterInstructionIndex: Int = 0 - private var viewRegister: Int = 0 - - /** - * Injects the code to change the visibility of controls. - * @param descriptor The descriptor of the method which should be called. - */ - fun injectVisibilityCheckCall(descriptor: String) { - showPlayerControlsFingerprintResult.mutableMethod.addInstruction( - 0, - """ - invoke-static {p1}, $descriptor - """ - ) - } - - /** - * Injects the code to initialize the controls. - * @param descriptor The descriptor of the method which should be calleed. - */ - fun initializeControl(descriptor: String) { - inflateFingerprintResult!!.mutableMethod.addInstruction( - moveToRegisterInstructionIndex + 1, - "invoke-static {v$viewRegister}, $descriptor" - ) - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt deleted file mode 100644 index fc63378..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/BottomControlsInflateFingerprint.kt +++ /dev/null @@ -1,27 +0,0 @@ -package app.revanced.patches.youtube.misc.playercontrols.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility -import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("bottom-controls-inflate-fingerprint") -@PlayerControlsCompatibility -@Version("0.0.1") -object BottomControlsInflateFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT - ), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { instruction -> - instruction.opcode.ordinal == Opcode.CONST.ordinal && - (instruction as? WideLiteralInstruction)?.wideLiteral == PlayerControlsBytecodePatch.bottomUiContainerResourceId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt deleted file mode 100644 index d2f0b1f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/fingerprints/PlayerControlsVisibilityFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.playercontrols.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility - -@Name("player-controls-visibility-fingerprint") -@PlayerControlsCompatibility -@Version("0.0.1") -object PlayerControlsVisibilityFingerprint : MethodFingerprint( - "V", - parameters = listOf("Z", "Z"), - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("YouTubeControlsOverlay;") - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt deleted file mode 100644 index fbba6ef..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playercontrols/resource/patch/BottomControlsResourcePatch.kt +++ /dev/null @@ -1,85 +0,0 @@ -package app.revanced.patches.youtube.misc.playercontrols.resource.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.DomFileEditor -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.playercontrols.annotation.PlayerControlsCompatibility - -@Name("bottom-controls-resource-patch") -@DependsOn([FixLocaleConfigErrorPatch::class]) -@Description("Manages the resources for the bottom controls of the YouTube player.") -@PlayerControlsCompatibility -@Version("0.0.1") -class BottomControlsResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - resourceContext = context - targetXmlEditor = context.xmlEditor[TARGET_RESOURCE] - - return PatchResultSuccess() - } - - companion object { - internal const val TARGET_RESOURCE_NAME = "youtube_controls_bottom_ui_container.xml" - private const val TARGET_RESOURCE = "res/layout/$TARGET_RESOURCE_NAME" - - private lateinit var resourceContext: ResourceContext - private lateinit var targetXmlEditor: DomFileEditor - - // The element to which to add the new elements to - private var lastLeftOf = "fullscreen_button" - - - - /** - * Add new controls to the bottom of the YouTube player. - * @param hostYouTubeControlsBottomUiResourceName The hosting resource name containing the elements. - */ - internal fun addControls(hostYouTubeControlsBottomUiResourceName: String) { - val sourceXmlEditor = - resourceContext.xmlEditor[this::class.java.classLoader.getResourceAsStream( - hostYouTubeControlsBottomUiResourceName - )!!] - - val targetElement = - "android.support.constraint.ConstraintLayout" - - val hostElements = sourceXmlEditor.file.getElementsByTagName(targetElement).item(0).childNodes - - val destinationResourceFile = this.targetXmlEditor.file - val destinationElement = - destinationResourceFile.getElementsByTagName(targetElement).item(0) - - for (index in 1 until hostElements.length) { - val element = hostElements.item(index).cloneNode(true) - - // if the element has no attributes theres no point to adding it to the destination - if (!element.hasAttributes()) continue - - // set the elements lastLeftOf attribute to the lastLeftOf value - val namespace = "@+id" - element.attributes.getNamedItem("yt:layout_constraintRight_toLeftOf").nodeValue = - "$namespace/$lastLeftOf" - - // set lastLeftOf attribute to the the current element - val nameSpaceLength = 4 - lastLeftOf = element.attributes.getNamedItem("android:id").nodeValue.substring(nameSpaceLength) - - // copy the element - destinationResourceFile.adoptNode(element) - destinationElement.appendChild(element) - } - sourceXmlEditor.close() - } - } - - override fun close() { - targetXmlEditor.close() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt deleted file mode 100644 index 6a0896f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/annotation/PlayerOverlaysHookCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.playeroverlay.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PlayerOverlaysHookCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt deleted file mode 100644 index f839116..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/fingerprint/PlayerOverlaysOnFinishInflateFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.playeroverlay.fingerprint - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.playeroverlay.annotation.PlayerOverlaysHookCompatibility - -@Name("player-overlays-onFinishInflate-fingerprint") -@PlayerOverlaysHookCompatibility -@Version("0.0.1") -object PlayerOverlaysOnFinishInflateFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("YouTubePlayerOverlaysLayout;") && methodDef.name == "onFinishInflate" - } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt deleted file mode 100644 index 9b1c95b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playeroverlay/patch/PlayerOverlaysHookPatch.kt +++ /dev/null @@ -1,35 +0,0 @@ -package app.revanced.patches.youtube.misc.playeroverlay.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.playeroverlay.annotation.PlayerOverlaysHookCompatibility -import app.revanced.patches.youtube.misc.playeroverlay.fingerprint.PlayerOverlaysOnFinishInflateFingerprint - -@Name("player-overlays-hook") -@Description("Hook for adding custom overlays to the video player.") -@PlayerOverlaysHookCompatibility -@Version("0.0.1") -@DependsOn([IntegrationsPatch::class]) -class PlayerOverlaysHookPatch : BytecodePatch( - listOf( - PlayerOverlaysOnFinishInflateFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - // hook YouTubePlayerOverlaysLayout.onFinishInflate() - val method = PlayerOverlaysOnFinishInflateFingerprint.result!!.mutableMethod - method.addInstruction( - method.implementation!!.instructions.size - 2, - "invoke-static { p0 }, Lapp/revanced/integrations/patches/PlayerOverlaysHookPatch;->YouTubePlayerOverlaysLayout_onFinishInflateHook(Ljava/lang/Object;)V" - ) - return PatchResultSuccess() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt deleted file mode 100644 index e54de73..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/annotation/PlayerTypeHookCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.playertype.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class PlayerTypeHookCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt deleted file mode 100644 index 34d0bec..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/fingerprint/UpdatePlayerTypeFingerprint.kt +++ /dev/null @@ -1,40 +0,0 @@ -package app.revanced.patches.youtube.misc.playertype.fingerprint - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -//TODO constrain to only match in YoutubePlayerOverlaysLayout? -@Name("update-player-type-fingerprint") -@FuzzyPatternScanMethod(2) -@SwipeControlsCompatibility -@Version("0.0.1") -object UpdatePlayerTypeFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - opcodes = listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.IGET_OBJECT, - Opcode.IF_NE, - Opcode.RETURN_VOID, - Opcode.IPUT_OBJECT, - Opcode.INVOKE_DIRECT, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.RETURN_VOID, - Opcode.CONST_4, - Opcode.INVOKE_STATIC, - Opcode.INVOKE_VIRTUAL, - Opcode.RETURN_VOID - ) -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt deleted file mode 100644 index 75e7220..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/playertype/patch/PlayerTypeHookPatch.kt +++ /dev/null @@ -1,34 +0,0 @@ -package app.revanced.patches.youtube.misc.playertype.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.playertype.annotation.PlayerTypeHookCompatibility -import app.revanced.patches.youtube.misc.playertype.fingerprint.UpdatePlayerTypeFingerprint - -@Name("player-type-hook") -@Description("Hook to get the current player type of WatchWhileActivity") -@PlayerTypeHookCompatibility -@Version("0.0.1") -@DependsOn([IntegrationsPatch::class]) -class PlayerTypeHookPatch : BytecodePatch( - listOf( - UpdatePlayerTypeFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - // hook YouTubePlayerOverlaysLayout.updatePlayerLayout() - UpdatePlayerTypeFingerprint.result!!.mutableMethod.addInstruction( - 0, - "invoke-static { p1 }, Lapp/revanced/integrations/patches/PlayerTypeHookPatch;->YouTubePlayerOverlaysLayout_updatePlayerTypeHookEX(Ljava/lang/Object;)V" - ) - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/annotations/SettingsCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/annotations/SettingsCompatibility.kt deleted file mode 100644 index 5fa1408..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/annotations/SettingsCompatibility.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility([Package("com.google.android.youtube")]) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class SettingsCompatibility \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt deleted file mode 100644 index 3770e86..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/LicenseActivityFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility - -// TODO: This is more of a class fingerprint than a method fingerprint. -// Convert to a class fingerprint whenever possible. -@Name("license-activity-fingerprint") -@SettingsCompatibility -@Version("0.0.1") -object LicenseActivityFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("LicenseActivity;") && methodDef.name == "onCreate" - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt deleted file mode 100644 index 1561678..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterAppFingerprint.kt +++ /dev/null @@ -1,39 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("theme-setter-app-fingerprint") -@SettingsCompatibility -@Version("0.0.1") -object ThemeSetterAppFingerprint : MethodFingerprint( - "L", AccessFlags.PUBLIC or AccessFlags.STATIC, listOf("L", "L", "L"), listOf( - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.IF_NE, - Opcode.CONST, //target reference - Opcode.GOTO, - Opcode.CONST, //target reference - Opcode.INVOKE_DIRECT, - Opcode.RETURN_OBJECT, - Opcode.NEW_INSTANCE, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.SGET_OBJECT, - Opcode.IF_NE, - Opcode.CONST, //target reference - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt deleted file mode 100644 index 366e674..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/fingerprints/ThemeSetterSystemFingerprint.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.bytecode.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.WideLiteralInstruction - -@Name("theme-setter-system-fingerprint") -@SettingsCompatibility -@Version("0.0.1") -object ThemeSetterSystemFingerprint : MethodFingerprint( - "L", - opcodes = listOf(Opcode.RETURN_OBJECT), - customFingerprint = { methodDef -> - methodDef.implementation?.instructions?.any { - it.opcode.ordinal == Opcode.CONST.ordinal && (it as WideLiteralInstruction).wideLiteral == SettingsResourcePatch.appearanceStringId - } == true - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt deleted file mode 100644 index 82cff22..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/bytecode/patch/SettingsPatch.kt +++ /dev/null @@ -1,185 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.bytecode.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility -import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.LicenseActivityFingerprint -import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterAppFingerprint -import app.revanced.patches.youtube.misc.settings.bytecode.fingerprints.ThemeSetterSystemFingerprint -import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference -import app.revanced.patches.youtube.misc.settings.framework.components.impl.Preference -import app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.resource.patch.SettingsResourcePatch -import org.jf.dexlib2.util.MethodUtil -import java.io.Closeable - -@Patch -@DependsOn( - [ - IntegrationsPatch::class, - SettingsResourcePatch::class, - ] -) -@Name("settings") -@Description("Adds settings for ReVanced to YouTube.") -@SettingsCompatibility -@Version("0.0.1") -class SettingsPatch : BytecodePatch( - listOf(LicenseActivityFingerprint, ThemeSetterSystemFingerprint, ThemeSetterAppFingerprint) -) { - override fun execute(context: BytecodeContext): PatchResult { - fun buildInvokeInstructionsString( - registers: String = "v0", - classDescriptor: String = THEME_HELPER_DESCRIPTOR, - methodName: String = SET_THEME_METHOD_NAME, - parameters: String = "Ljava/lang/Object;" - ) = "invoke-static {$registers}, $classDescriptor->$methodName($parameters)V" - - // apply the current theme of the settings page - with(ThemeSetterSystemFingerprint.result!!) { - with(mutableMethod) { - val call = buildInvokeInstructionsString() - - addInstruction( - scanResult.patternScanResult!!.startIndex, - call - ) - - addInstruction( - mutableMethod.implementation!!.instructions.size - 1, - call - ) - } - } - - // set the theme based on the preference of the app - with(ThemeSetterAppFingerprint.result!!) { - with(mutableMethod) { - fun buildInstructionsString(theme: Int) = """ - const/4 v0, 0x$theme - ${buildInvokeInstructionsString(parameters = "I")} - """ - - addInstructions( - scanResult.patternScanResult!!.endIndex + 1, - buildInstructionsString(1) - ) - addInstructions( - scanResult.patternScanResult!!.endIndex - 7, - buildInstructionsString(0) - ) - - addInstructions( - scanResult.patternScanResult!!.endIndex - 9, - buildInstructionsString(1) - ) - addInstructions( - mutableMethod.implementation!!.instructions.size - 2, - buildInstructionsString(0) - ) - } - } - - // set the theme based on the preference of the device - with(LicenseActivityFingerprint.result!!) licenseActivity@{ - with(mutableMethod) { - fun buildSettingsActivityInvokeString( - registers: String = "p0", - classDescriptor: String = SETTINGS_ACTIVITY_DESCRIPTOR, - methodName: String = "initializeSettings", - parameters: String = this@licenseActivity.mutableClass.type - ) = buildInvokeInstructionsString(registers, classDescriptor, methodName, parameters) - - // initialize the settings - addInstructions( - 1, - """ - ${buildSettingsActivityInvokeString()} - return-void - """ - ) - - // set the current theme - addInstruction(0, buildSettingsActivityInvokeString(methodName = "setTheme")) - } - - // remove method overrides - with(mutableClass) { - methods.removeIf { it.name != "onCreate" && !MethodUtil.isConstructor(it) } - } - } - - return PatchResultSuccess() - } - - internal companion object { - private const val INTEGRATIONS_PACKAGE = "app/revanced/integrations" - - private const val SETTINGS_ACTIVITY_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/settingsmenu/ReVancedSettingActivity;" - - private const val THEME_HELPER_DESCRIPTOR = "L$INTEGRATIONS_PACKAGE/utils/ThemeHelper;" - private const val SET_THEME_METHOD_NAME = "setTheme" - - fun addString(identifier: String, value: String, formatted: Boolean = true) = - SettingsResourcePatch.addString(identifier, value, formatted) - - fun addPreferenceScreen(preferenceScreen: app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen) = - SettingsResourcePatch.addPreferenceScreen(preferenceScreen) - - fun addPreference(preference: Preference) = - SettingsResourcePatch.addPreference(preference) - - fun renameIntentsTargetPackage(newPackage: String) { - SettingsResourcePatch.overrideIntentsTargetPackage = newPackage - } - } - - /** - * Preference screens patches should add their settings to. - */ - internal enum class PreferenceScreen( - private val key: String, - private val title: String, - private val summary: String? = null, - private val preferences: MutableList = mutableListOf() - ) : Closeable { - ADS("ads", "Ads", "Ad related settings"), - INTERACTIONS("interactions", "Interaction", "Settings related to interactions"), - LAYOUT("layout", "Layout", "Settings related to the layout"), - MISC("misc", "Miscellaneous", "Miscellaneous patches"); - - override fun close() { - if (preferences.size == 0) return - - addPreferenceScreen( - PreferenceScreen( - key, - StringResource("${key}_title", title), - preferences, - summary?.let { summary -> - StringResource("${key}_summary", summary) - } - ) - ) - } - - /** - * Add preferences to the preference screen. - */ - fun addPreferences(vararg preferences: BasePreference) = this.preferences.addAll(preferences) - } - - override fun close() = PreferenceScreen.values().forEach(PreferenceScreen::close) - -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/BasePreference.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/BasePreference.kt deleted file mode 100644 index da9e7a1..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/BasePreference.kt +++ /dev/null @@ -1,14 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components - -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource - -/** - * Base preference class for all preferences. - * - * @param key The key of the preference. - * @param title The title of the preference. - */ -internal abstract class BasePreference( - override val key: String, - override val title: StringResource, -) : IPreference \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/IPreference.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/IPreference.kt deleted file mode 100644 index bf25a62..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/IPreference.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components - -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource - -/** - * Preference - */ -internal interface IPreference { - /** - * Key of the preference. - */ - val key: String - - /** - * Title of the preference. - */ - val title: StringResource - - /** - * Tag name of the preference. - */ - val tag: String -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/ArrayResource.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/ArrayResource.kt deleted file mode 100644 index c2c60dc..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/ArrayResource.kt +++ /dev/null @@ -1,9 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -/** - * Represents an array resource. - * - * @param name The name of the array resource. - * @param items The items of the array resource. - */ -internal data class ArrayResource(val name: String, val items: List) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/InputType.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/InputType.kt deleted file mode 100644 index 53b54a2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/InputType.kt +++ /dev/null @@ -1,6 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -enum class InputType(val type: String) { - STRING("text"), - NUMBER("number"), -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/Preference.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/Preference.kt deleted file mode 100644 index 6818b5c..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/Preference.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -/** - * A Preference object. - * - * @param title The title of the preference. - * @param intent The intent of the preference. - * @param summary The summary of the text preference. - */ -internal class Preference( - val title: StringResource, - val intent: Intent, - val summary: StringResource? = null -) { - val tag: String = "Preference" - - data class Intent(val targetPackage: String, val data: String, val targetClass: String) -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/PreferenceScreen.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/PreferenceScreen.kt deleted file mode 100644 index 9087540..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/PreferenceScreen.kt +++ /dev/null @@ -1,20 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference - -/** - * Preference screen. - * - * @param key The key of the preference. - * @param title The title of the preference. - * @param preferences Child preferences of this screen. - * @param summary The summary of the text preference. - */ -internal open class PreferenceScreen( - key: String, - title: StringResource, - val preferences: List, - var summary: StringResource? = null -) : BasePreference(key, title) { - override val tag: String = "PreferenceScreen" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/StringResource.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/StringResource.kt deleted file mode 100644 index 7c731cc..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/StringResource.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -/** - * Represents a string value in the strings.xml file - * - * @param name The name of the string - * @param value The value of the string - * @param formatted If the string is formatted. If false, the attribute will be set - */ -internal data class StringResource(val name: String, val value: String, val formatted: Boolean = true) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/SwitchPreference.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/SwitchPreference.kt deleted file mode 100644 index e98d60e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/SwitchPreference.kt +++ /dev/null @@ -1,21 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference - -/** - * Switch preference. - * - * @param key The key of the switch. - * @param title The title of the switch. - * @param default The default value of the switch. - * @param summaryOn The summary to show when the preference is enabled. - * @param summaryOff The summary to show when the preference is disabled. - */ -internal class SwitchPreference( - key: String, title: StringResource, - val default: Boolean = false, - var summaryOn: StringResource? = null, - var summaryOff: StringResource? = null -) : BasePreference(key, title) { - override val tag: String = "SwitchPreference" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/TextPreference.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/TextPreference.kt deleted file mode 100644 index e348e37..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/framework/components/impl/TextPreference.kt +++ /dev/null @@ -1,22 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.framework.components.impl - -import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference - -/** - * Text preference. - * - * @param key The key of the text preference. - * @param title The title of the text preference. - * @param inputType The input type of the text preference. - * @param default The default value of the text preference. - * @param summary The summary of the text preference. - */ -internal class TextPreference( - key: String, - title: StringResource, - var inputType: InputType = InputType.STRING, - var default: String? = null, - var summary: StringResource? = null -) : BasePreference(key, title) { - override val tag: String = "EditTextPreference" -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt deleted file mode 100644 index d6ab6ab..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/settings/resource/patch/SettingsResourcePatch.kt +++ /dev/null @@ -1,302 +0,0 @@ -package app.revanced.patches.youtube.misc.settings.resource.patch - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.DomFileEditor -import app.revanced.patcher.data.ResourceContext -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.ResourcePatch -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patches.youtube.misc.manifest.patch.FixLocaleConfigErrorPatch -import app.revanced.patches.youtube.misc.mapping.patch.ResourceMappingResourcePatch -import app.revanced.patches.youtube.misc.settings.annotations.SettingsCompatibility -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.BasePreference -import app.revanced.patches.youtube.misc.settings.framework.components.impl.* -import app.revanced.util.resources.ResourceUtils -import app.revanced.util.resources.ResourceUtils.copyResources -import org.w3c.dom.Element -import org.w3c.dom.Node - -@Name("settings-resource-patch") -@SettingsCompatibility -@DependsOn([FixLocaleConfigErrorPatch::class, ResourceMappingResourcePatch::class]) -@Version("0.0.1") -class SettingsResourcePatch : ResourcePatch { - override fun execute(context: ResourceContext): PatchResult { - /* - * used by a fingerprint of SettingsPatch - */ - appearanceStringId = ResourceMappingResourcePatch.resourceMappings.find { - it.type == "string" && it.name == "app_theme_appearance_dark" - }!!.id - - /* - * create missing directory for the resources - */ - context["res/drawable-ldrtl-xxxhdpi"].mkdirs() - - /* - * copy layout resources - */ - arrayOf( - ResourceUtils.ResourceGroup( - "layout", - "revanced_settings_toolbar.xml", - "revanced_settings_with_toolbar.xml", - "revanced_settings_with_toolbar_layout.xml" - ), ResourceUtils.ResourceGroup( - "xml", "revanced_prefs.xml" // template for new preferences - ), ResourceUtils.ResourceGroup( - // required resource for back button, because when the base APK is used, this resource will not exist - "drawable-xxxhdpi", "quantum_ic_arrow_back_white_24.png" - ), ResourceUtils.ResourceGroup( - // required resource for back button, because when the base APK is used, this resource will not exist - "drawable-ldrtl-xxxhdpi", "quantum_ic_arrow_back_white_24.png" - ) - ).forEach { resourceGroup -> - context.copyResources("settings", resourceGroup) - } - - context.xmlEditor["AndroidManifest.xml"].use { editor -> - editor.file.getElementsByTagName("manifest").item(0).also { - it.appendChild(it.ownerDocument.createElement("uses-permission").also { element -> - element.setAttribute("android:name", "android.permission.SCHEDULE_EXACT_ALARM") - }) - } - } - - revancedPreferencesEditor = context.xmlEditor["res/xml/revanced_prefs.xml"] - preferencesEditor = context.xmlEditor["res/xml/settings_fragment.xml"] - - stringsEditor = context.xmlEditor["res/values/strings.xml"] - arraysEditor = context.xmlEditor["res/values/arrays.xml"] - - // Add the ReVanced settings to the YouTube settings - val youtubePackage = "com.google.android.youtube" - SettingsPatch.addPreference( - Preference( - StringResource("revanced_settings", "ReVanced"), - Preference.Intent( - youtubePackage, "revanced_settings", "com.google.android.libraries.social.licenses.LicenseActivity" - ), - StringResource("revanced_settings_summary", "ReVanced specific settings"), - ) - ) - - return PatchResultSuccess() - } - - - internal companion object { - // Used by a fingerprint of SettingsPatch - // this field is located in the SettingsResourcePatch - // because if it were to be defined in the SettingsPatch companion object, - // the companion object could be initialized before ResourceMappingResourcePatch has executed. - internal var appearanceStringId: Long = -1 - - // if this is not null, all intents will be renamed to this - var overrideIntentsTargetPackage: String? = null - - private var revancedPreferenceNode: Node? = null - private var preferencesNode: Node? = null - - private var stringsNode: Node? = null - private var arraysNode: Node? = null - - private var strings = mutableListOf() - - private var revancedPreferencesEditor: DomFileEditor? = null - set(value) { - field = value - revancedPreferenceNode = value.getNode("PreferenceScreen") - } - private var preferencesEditor: DomFileEditor? = null - set(value) { - field = value - preferencesNode = value.getNode("PreferenceScreen") - } - - private var stringsEditor: DomFileEditor? = null - set(value) { - field = value - stringsNode = value.getNode("resources") - } - private var arraysEditor: DomFileEditor? = null - set(value) { - field = value - arraysNode = value.getNode("resources") - } - - /** - * Add a new string to the resources. - * - * @param identifier The key of the string. - * @param value The value of the string. - * @throws IllegalArgumentException if the string already exists. - */ - fun addString(identifier: String, value: String, formatted: Boolean) = - StringResource(identifier, value, formatted).include() - - /** - * Add an array to the resources. - * - * @param arrayResource The array resource to add. - */ - fun addArray(arrayResource: ArrayResource) { - arraysNode!!.appendChild(arraysNode!!.ownerDocument.createElement("string-array").also { arrayNode -> - arrayResource.items.forEach { item -> - item.include() - - arrayNode.setAttribute("name", item.name) - - arrayNode.appendChild(arrayNode.ownerDocument.createElement("item").also { itemNode -> - itemNode.textContent = item.value - }) - } - }) - } - - /** - * Add a preference screen to the settings. - * - * @param preferenceScreen The name of the preference screen. - */ - fun addPreferenceScreen(preferenceScreen: PreferenceScreen) = - revancedPreferenceNode!!.addPreference(preferenceScreen) - - /** - * Add a preference fragment to the preferences. - * - * @param preference The preference to add. - */ - fun addPreference(preference: Preference) { - preferencesNode!!.appendChild(preferencesNode.createElement(preference.tag).also { preferenceNode -> - preferenceNode.setAttribute( - "android:title", "@string/${preference.title.also { it.include() }.name}" - ) - preference.summary?.let { summary -> - preferenceNode.setAttribute("android:summary", "@string/${summary.also { it.include() }.name}") - } - - preferenceNode.appendChild(preferenceNode.createElement("intent").also { intentNode -> - intentNode.setAttribute("android:targetPackage", preference.intent.targetPackage) - intentNode.setAttribute("android:data", preference.intent.data) - intentNode.setAttribute("android:targetClass", preference.intent.targetClass) - }) - }) - } - - - /** - * Add a preference to the settings. - * - * @param preference The preference to add. - */ - private fun Node.addPreference(preference: BasePreference) { - // add a summary to the element - fun Element.addSummary(summaryResource: StringResource?, summaryType: SummaryType = SummaryType.DEFAULT) = - summaryResource?.let { summary -> - setAttribute("android:${summaryType.type}", "@string/${summary.also { it.include() }.name}") - } - - fun Element.addDefault(default: T) { - default?.let { - setAttribute( - "android:defaultValue", when (it) { - is Boolean -> if (it) "true" else "false" - is String -> it - else -> throw IllegalArgumentException("Unsupported default value type: ${it::class.java.name}") - } - ) - } - } - - val preferenceElement = ownerDocument.createElement(preference.tag) - preferenceElement.setAttribute("android:key", preference.key) - preferenceElement.setAttribute("android:title", "@string/${preference.title.also { it.include() }.name}") - - when (preference) { - is PreferenceScreen -> { - for (childPreference in preference.preferences) preferenceElement.addPreference(childPreference) - preferenceElement.addSummary(preference.summary) - } - is SwitchPreference -> { - preferenceElement.addDefault(preference.default) - preferenceElement.addSummary(preference.summaryOn, SummaryType.ON) - preferenceElement.addSummary(preference.summaryOff, SummaryType.OFF) - } - is TextPreference -> { - preferenceElement.setAttribute("android:inputType", preference.inputType.type) - preferenceElement.addDefault(preference.default) - preferenceElement.addSummary(preference.summary) - } - } - - appendChild(preferenceElement) - } - - /** - * Add a new string to the resources. - * - * @throws IllegalArgumentException if the string already exists. - */ - private fun StringResource.include() { - if (strings.any { it.name == name }) return - strings.add(this) - } - - private fun DomFileEditor?.getNode(tagName: String) = this!!.file.getElementsByTagName(tagName).item(0) - - private fun Node?.createElement(tagName: String) = this!!.ownerDocument.createElement(tagName) - - private enum class SummaryType(val type: String) { - DEFAULT("summary"), ON("summaryOn"), OFF("summaryOff") - } - } - - override fun close() { - // merge all strings, skip duplicates - strings.forEach { stringResource -> - stringsNode!!.appendChild(stringsNode!!.ownerDocument.createElement("string").also { stringElement -> - stringElement.setAttribute("name", stringResource.name) - - // if the string is un-formatted, explicitly add the formatted attribute - if (!stringResource.formatted) stringElement.setAttribute("formatted", "false") - - stringElement.textContent = stringResource.value - }) - } - - // rename the intent package names if it was set - overrideIntentsTargetPackage?.let { packageName -> - val preferences = preferencesEditor!!.getNode("PreferenceScreen").childNodes - for (i in 1 until preferences.length) { - val preferenceNode = preferences.item(i) - // preferences have a child node with the intent tag, skip over every other node - if (preferenceNode.childNodes.length == 0) continue - - val intentNode = preferenceNode.firstChild - - // if the node doesn't have a target package attribute, skip it - val targetPackageAttribute = intentNode.attributes.getNamedItem("android:targetPackage") ?: continue - - // do not replace intent target package if the package name is not from YouTube - val youtubePackage = "com.google.android.youtube" - if (targetPackageAttribute.nodeValue != youtubePackage) continue - - // replace the target package name - intentNode.attributes.setNamedItem(preferenceNode.ownerDocument.createAttribute("android:targetPackage") - .also { attribute -> - attribute.value = packageName - }) - } - } - - revancedPreferencesEditor?.close() - preferencesEditor?.close() - stringsEditor?.close() - arraysEditor?.close() - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt deleted file mode 100644 index 7c1ccb8..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/annotation/VideoInformationCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.41.37") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class VideoInformationCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt deleted file mode 100644 index c5fe869..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/CreateVideoPlayerSeekbarFingerprint.kt +++ /dev/null @@ -1,16 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility - -@Name("create-video-player-seekbar-fingerprint") -@VideoInformationCompatibility -@Version("0.0.1") -object CreateVideoPlayerSeekbarFingerprint : MethodFingerprint( - "V", - strings = listOf("timed_markers_width") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt deleted file mode 100644 index 42b953b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerControllerSetTimeReferenceFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility -import org.jf.dexlib2.Opcode - -@Name("player-controller-set-time-reference-fingerprint") -@VideoInformationCompatibility -@Version("0.0.1") -object PlayerControllerSetTimeReferenceFingerprint : MethodFingerprint( - opcodes = listOf(Opcode.INVOKE_DIRECT_RANGE, Opcode.IGET_OBJECT), - strings = listOf("Media progress reported outside media playback: ") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt deleted file mode 100644 index 2e7f3a0..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/PlayerInitFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility - -@Name("player-init-fingerprint") -@VideoInformationCompatibility -@Version("0.0.1") -object PlayerInitFingerprint : MethodFingerprint( - strings = listOf( - "playVideo called on player response with no videoStreamingData." - ), -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt deleted file mode 100644 index 2e7851e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/SeekFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility - -@Name("seek-fingerprint") -@VideoInformationCompatibility -@Version("0.0.1") -object SeekFingerprint : MethodFingerprint( - strings = listOf("Attempting to seek during an ad") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt deleted file mode 100644 index 1457d8e..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoLengthFingerprint.kt +++ /dev/null @@ -1,29 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility -import org.jf.dexlib2.Opcode - -@Name("video-length-fingerprint") -@VideoInformationCompatibility -@Version("0.0.1") -object VideoLengthFingerprint : MethodFingerprint( - opcodes = listOf( - Opcode.MOVE_RESULT_WIDE, - Opcode.CMP_LONG, - Opcode.IF_LEZ, - Opcode.IGET_OBJECT, - Opcode.CHECK_CAST, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.GOTO, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_WIDE, - Opcode.CONST_4, - Opcode.INVOKE_VIRTUAL - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt deleted file mode 100644 index cfcf2d8..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/fingerprints/VideoTimeFingerprint.kt +++ /dev/null @@ -1,15 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility - -@Name("video-time-fingerprint") -@VideoInformationCompatibility -@Version("0.0.1") -object VideoTimeFingerprint : MethodFingerprint( - strings = listOf("MedialibPlayerTimeInfo{currentPositionMillis=") -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt deleted file mode 100644 index 4df446b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt +++ /dev/null @@ -1,178 +0,0 @@ -package app.revanced.patches.youtube.misc.video.information.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.data.toMethodWalker -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.video.information.annotation.VideoInformationCompatibility -import app.revanced.patches.youtube.misc.video.information.fingerprints.* -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.builder.MutableMethodImplementation -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.immutable.ImmutableMethod -import org.jf.dexlib2.immutable.ImmutableMethodParameter -import org.jf.dexlib2.util.MethodUtil - -@Name("video-information") -@Description("Hooks YouTube to get information about the current playing video.") -@VideoInformationCompatibility -@Version("0.0.1") -@DependsOn([IntegrationsPatch::class]) -class VideoInformationPatch : BytecodePatch( - listOf( - PlayerInitFingerprint, - CreateVideoPlayerSeekbarFingerprint, - PlayerControllerSetTimeReferenceFingerprint, - VideoTimeFingerprint, - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - with(PlayerInitFingerprint.result!!) { - playerInitMethod = mutableClass.methods.first { MethodUtil.isConstructor(it) } - - // hook the player controller for use through integrations - onCreateHook(INTEGRATIONS_CLASS_DESCRIPTOR, "playerController_onCreateHook") - - // seek method - val seekFingerprintResultMethod = SeekFingerprint.also { it.resolve(context, classDef) }.result!!.method - - // create helper method - val seekHelperMethod = ImmutableMethod( - seekFingerprintResultMethod.definingClass, - "seekTo", - listOf(ImmutableMethodParameter("J", null, "time")), - "Z", - AccessFlags.PUBLIC or AccessFlags.FINAL, - null, null, - MutableMethodImplementation(4) - ).toMutable() - - // get enum type for the seek helper method - val seekSourceEnumType = seekFingerprintResultMethod.parameterTypes[1].toString() - - // insert helper method instructions - seekHelperMethod.addInstructions( - 0, - """ - sget-object v0, $seekSourceEnumType->a:$seekSourceEnumType - invoke-virtual {p0, p1, p2, v0}, ${seekFingerprintResultMethod.definingClass}->${seekFingerprintResultMethod.name}(J$seekSourceEnumType)Z - move-result p1 - return p1 - """ - ) - - // add the seekTo method to the class for the integrations to call - mutableClass.methods.add(seekHelperMethod) - } - - with(CreateVideoPlayerSeekbarFingerprint.result!!) { - val videoLengthMethodResult = VideoLengthFingerprint.also { it.resolve(context, classDef) }.result!! - - with(videoLengthMethodResult.mutableMethod) { - val videoLengthRegisterIndex = videoLengthMethodResult.scanResult.patternScanResult!!.endIndex - 2 - val videoLengthRegister = (instruction(videoLengthRegisterIndex) as OneRegisterInstruction).registerA - val dummyRegisterForLong = videoLengthRegister + 1 // required for long values since they are wide - - addInstruction( - videoLengthMethodResult.scanResult.patternScanResult!!.endIndex, - "invoke-static {v$videoLengthRegister, v$dummyRegisterForLong}, $INTEGRATIONS_CLASS_DESCRIPTOR->setVideoLength(J)V" - ) - } - } - - /* - Set the video time method - */ - with(PlayerControllerSetTimeReferenceFingerprint.result!!) { - timeMethod = context.toMethodWalker(method) - .nextMethod(scanResult.patternScanResult!!.startIndex, true) - .getMethod() as MutableMethod - } - - /* - Set the high precision video time method - */ - highPrecisionTimeMethod = - (object : MethodFingerprint("V", null, listOf("J", "J", "J", "J", "I", "L"), null) {}).also { - it.resolve(context, VideoTimeFingerprint.result!!.classDef) - }.result!!.mutableMethod - - /* - Hook the methods which set the time - */ - highPrecisionTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTime") - - return PatchResultSuccess() - } - - companion object { - private const val INTEGRATIONS_CLASS_DESCRIPTOR = "Lapp/revanced/integrations/patches/VideoInformation;" - - private lateinit var playerInitMethod: MutableMethod - private lateinit var timeMethod: MutableMethod - private lateinit var highPrecisionTimeMethod: MutableMethod - - private fun MutableMethod.insert(insert: InsertIndex, register: String, descriptor: String) = - addInstruction(insert.index, "invoke-static { $register }, $descriptor") - - private fun MutableMethod.insertTimeHook(insert: InsertIndex, descriptor: String) = - insert(insert, "p1, p2", descriptor) - - /** - * Hook the player controller. - * - * @param targetMethodClass The descriptor for the class to invoke when the player controller is created. - * @param targetMethodName The name of the static method to invoke when the player controller is created. - */ - internal fun onCreateHook(targetMethodClass: String, targetMethodName: String) = - playerInitMethod.insert( - InsertIndex.CREATE, - "v0", - "$targetMethodClass->$targetMethodName(Ljava/lang/Object;)V" - ) - - /** - * Hook the video time. - * - * @param targetMethodClass The descriptor for the static method to invoke when the player controller is created. - * @param targetMethodName The name of the static method to invoke when the player controller is created. - */ - internal fun videoTimeHook(targetMethodClass: String, targetMethodName: String) = - timeMethod.insertTimeHook( - InsertIndex.TIME, - "$targetMethodClass->$targetMethodName(J)V" - ) - - /** - * Hook the high precision video time. - * - * @param targetMethodClass The descriptor for the static method to invoke when the player controller is created. - * @param targetMethodName The name of the static method to invoke when the player controller is created. - */ - internal fun highPrecisionTimeHook(targetMethodClass: String, targetMethodName: String) = - highPrecisionTimeMethod.insertTimeHook( - InsertIndex.HIGH_PRECISION_TIME, - "$targetMethodClass->$targetMethodName(J)V" - ) - - enum class InsertIndex(internal val index: Int) { - CREATE(4), - TIME(2), - HIGH_PRECISION_TIME(0), - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt deleted file mode 100644 index 31d8da2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/annotations/RememberVideoQualityCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.video.quality.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class RememberVideoQualityCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt deleted file mode 100644 index b799bd2..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualityReferenceFingerprint.kt +++ /dev/null @@ -1,18 +0,0 @@ -package app.revanced.patches.youtube.misc.video.quality.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.video.quality.annotations.RememberVideoQualityCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("video-quality-reference-fingerprint") -@RememberVideoQualityCompatibility -@Version("0.0.1") -object VideoQualityReferenceFingerprint : MethodFingerprint( - "V", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf("L"), listOf( - Opcode.IPUT_OBJECT, Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt deleted file mode 100644 index 333a9d1..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoQualitySetterFingerprint.kt +++ /dev/null @@ -1,27 +0,0 @@ - -package app.revanced.patches.youtube.misc.video.quality.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.video.quality.annotations.RememberVideoQualityCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("video-quality-setter-fingerprint") -@RememberVideoQualityCompatibility -@Version("0.0.1") -object VideoQualitySetterFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("[L", "I", "I", "Z", "I"), - listOf( - Opcode.IF_EQZ, - Opcode.INVOKE_VIRTUAL, - Opcode.MOVE_RESULT_OBJECT, - Opcode.INVOKE_VIRTUAL, - Opcode.IPUT_BOOLEAN, - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt deleted file mode 100644 index e270616..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/fingerprints/VideoUserQualityChangeFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ - -package app.revanced.patches.youtube.misc.video.quality.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint - -import app.revanced.patches.youtube.misc.video.quality.annotations.RememberVideoQualityCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("video-user-quality-change-fingerprint") -@RememberVideoQualityCompatibility -@Version("0.0.1") -object VideoUserQualityChangeFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("L","L","I","J"), - listOf( - Opcode.MOVE, - Opcode.MOVE_WIDE, - Opcode.INVOKE_INTERFACE_RANGE, - Opcode.RETURN_VOID - ) -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt deleted file mode 100644 index a998eaf..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/quality/patch/RememberVideoQualityPatch.kt +++ /dev/null @@ -1,88 +0,0 @@ -package app.revanced.patches.youtube.misc.video.quality.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolve -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.video.quality.annotations.RememberVideoQualityCompatibility -import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualityReferenceFingerprint -import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoQualitySetterFingerprint -import app.revanced.patches.youtube.misc.video.quality.fingerprints.VideoUserQualityChangeFingerprint -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.SwitchPreference -import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference - -@Patch -@DependsOn([IntegrationsPatch::class, VideoIdPatch::class, SettingsPatch::class]) -@Name("remember-video-quality") -@Description("Adds the ability to remember the video quality you chose in the video quality flyout.") -@RememberVideoQualityCompatibility -@Version("0.0.1") -class RememberVideoQualityPatch : BytecodePatch( - listOf( - VideoQualitySetterFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - SwitchPreference( - "revanced_remember_video_quality_selection", - StringResource("revanced_remember_video_quality_selection_title", "Remember current video quality"), - false, - StringResource( - "revanced_remember_video_quality_selection_summary_on", - "The current video quality will not change" - ), - StringResource( - "revanced_remember_video_quality_selection_summary_off", - "Video quality will be remembered until a new quality is chosen" - ) - ) - ) - - val setterMethod = VideoQualitySetterFingerprint.result!! - - VideoUserQualityChangeFingerprint.resolve(context, setterMethod.classDef) - val userQualityMethod = VideoUserQualityChangeFingerprint.result!! - - VideoQualityReferenceFingerprint.resolve(context, setterMethod.classDef) - val qualityFieldReference = - VideoQualityReferenceFingerprint.result!!.method.let { method -> - (method.implementation!!.instructions.elementAt(0) as ReferenceInstruction).reference as FieldReference - } - - VideoIdPatch.injectCall("Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;->newVideoStarted(Ljava/lang/String;)V") - - val qIndexMethodName = - context.classes.single { it.type == qualityFieldReference.type }.methods.single { it.parameterTypes.first() == "I" }.name - - setterMethod.mutableMethod.addInstructions( - 0, - """ - iget-object v0, p0, ${setterMethod.classDef.type}->${qualityFieldReference.name}:${qualityFieldReference.type} - const-string v1, "$qIndexMethodName" - invoke-static {p1, p2, v0, v1}, Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;->setVideoQuality([Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/String;)I - move-result p2 - """, - ) - - userQualityMethod.mutableMethod.addInstruction( - 0, - "invoke-static {p3}, Lapp/revanced/integrations/patches/playback/quality/RememberVideoQualityPatch;->userChangedQuality(I)V" - ) - - return PatchResultSuccess() - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt deleted file mode 100644 index 56d1e77..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/annotations/CustomPlaybackSpeedCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.video.speed.custom.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CustomPlaybackSpeedCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt deleted file mode 100644 index 45f0cc1..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedArrayGeneratorFingerprint.kt +++ /dev/null @@ -1,28 +0,0 @@ -package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("speed-array-generator-fingerprint") -@FuzzyPatternScanMethod(2) -@CustomPlaybackSpeedCompatibility -@Version("0.0.1") -object SpeedArrayGeneratorFingerprint : MethodFingerprint( - "[L", - AccessFlags.PUBLIC or AccessFlags.STATIC, - opcodes = listOf( - Opcode.IF_NEZ, - Opcode.SGET_OBJECT, - Opcode.GOTO, - Opcode.INVOKE_INTERFACE, - Opcode.MOVE_RESULT_OBJECT, - Opcode.IGET_OBJECT, - ), - strings = listOf("0.0#") -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt deleted file mode 100644 index 0db8b5b..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/SpeedLimiterFingerprint.kt +++ /dev/null @@ -1,30 +0,0 @@ -package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or -import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("speed-limiter-fingerprint") -@FuzzyPatternScanMethod(2) -@CustomPlaybackSpeedCompatibility -@Version("0.0.1") -object SpeedLimiterFingerprint : MethodFingerprint( - "V", - AccessFlags.PUBLIC or AccessFlags.FINAL, - listOf("F"), - listOf( - Opcode.INVOKE_STATIC, - Opcode.MOVE_RESULT, - Opcode.IF_EQZ, - Opcode.CONST_HIGH16, - Opcode.GOTO, - Opcode.CONST_HIGH16, - Opcode.CONST_HIGH16, - Opcode.INVOKE_STATIC, - ), -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt deleted file mode 100644 index f452225..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/fingerprints/VideoSpeedPatchFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.patches.youtube.misc.video.speed.custom.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility -import org.jf.dexlib2.Opcode - -@Name("video-speed-patch-fingerprint") -@CustomPlaybackSpeedCompatibility -@Version("0.0.1") -object VideoSpeedPatchFingerprint : MethodFingerprint( - opcodes = listOf(Opcode.FILL_ARRAY_DATA), - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("CustomVideoSpeedPatch;") && methodDef.name == "" - } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt deleted file mode 100644 index 1b76883..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/speed/custom/patch/CustomVideoSpeedPatch.kt +++ /dev/null @@ -1,195 +0,0 @@ -package app.revanced.patches.youtube.misc.video.speed.custom.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.patch.* -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patches.youtube.misc.video.speed.custom.annotations.CustomPlaybackSpeedCompatibility -import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedArrayGeneratorFingerprint -import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.SpeedLimiterFingerprint -import app.revanced.patches.youtube.misc.video.speed.custom.fingerprints.VideoSpeedPatchFingerprint -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import org.jf.dexlib2.builder.instruction.BuilderArrayPayload -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction -import org.jf.dexlib2.iface.instruction.ReferenceInstruction -import org.jf.dexlib2.iface.reference.FieldReference -import org.jf.dexlib2.iface.reference.MethodReference -import java.util.stream.DoubleStream -import kotlin.math.roundToInt - -@Patch -@Name("custom-video-speed") -@Description("Adds more video speed options.") -@DependsOn([IntegrationsPatch::class]) -@CustomPlaybackSpeedCompatibility -@Version("0.0.1") -class CustomVideoSpeedPatch : BytecodePatch( - listOf( - SpeedArrayGeneratorFingerprint, SpeedLimiterFingerprint, VideoSpeedPatchFingerprint - ) -) { - - override fun execute(context: BytecodeContext): PatchResult { - val speedLimitMin = minVideoSpeed!!.toFloat() - val speedLimitMax = maxVideoSpeed!!.toFloat().coerceAtLeast(speedLimitMin) - val speedsGranularity = videoSpeedsGranularity!!.toFloat() - - val arrayGenMethod = SpeedArrayGeneratorFingerprint.result?.mutableMethod!! - val arrayGenMethodImpl = arrayGenMethod.implementation!! - - val sizeCallIndex = arrayGenMethodImpl.instructions - .indexOfFirst { ((it as? ReferenceInstruction)?.reference as? MethodReference)?.name == "size" } - - if (sizeCallIndex == -1) return PatchResultError("Couldn't find call to size()") - - val sizeCallResultRegister = - (arrayGenMethodImpl.instructions.elementAt(sizeCallIndex + 1) as OneRegisterInstruction).registerA - - arrayGenMethod.replaceInstruction( - sizeCallIndex + 1, - "const/4 v$sizeCallResultRegister, 0x0" - ) - - val (arrayLengthConstIndex, arrayLengthConst) = arrayGenMethodImpl.instructions.withIndex() - .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 7 } - - val arrayLengthConstDestination = (arrayLengthConst as OneRegisterInstruction).registerA - - val videoSpeedsArrayType = "Lapp/revanced/integrations/patches/playback/speed/CustomVideoSpeedPatch;->videoSpeeds:[F" - - arrayGenMethod.addInstructions( - arrayLengthConstIndex + 1, - """ - sget-object v$arrayLengthConstDestination, $videoSpeedsArrayType - array-length v$arrayLengthConstDestination, v$arrayLengthConstDestination - """ - ) - - val (originalArrayFetchIndex, originalArrayFetch) = arrayGenMethodImpl.instructions.withIndex() - .first { - val reference = ((it.value as? ReferenceInstruction)?.reference as? FieldReference) - reference?.definingClass?.contains("PlayerConfigModel") ?: false && - reference?.type == "[F" - } - - val originalArrayFetchDestination = (originalArrayFetch as OneRegisterInstruction).registerA - - arrayGenMethod.replaceInstruction( - originalArrayFetchIndex, - "sget-object v$originalArrayFetchDestination, $videoSpeedsArrayType" - ) - - val limiterMethod = SpeedLimiterFingerprint.result?.mutableMethod!! - val limiterMethodImpl = limiterMethod.implementation!! - - val (limiterMinConstIndex, limiterMinConst) = limiterMethodImpl.instructions.withIndex() - .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 0.25f.toRawBits() } - val (limiterMaxConstIndex, limiterMaxConst) = limiterMethodImpl.instructions.withIndex() - .first { (it.value as? NarrowLiteralInstruction)?.narrowLiteral == 2.0f.toRawBits() } - - val limiterMinConstDestination = (limiterMinConst as OneRegisterInstruction).registerA - val limiterMaxConstDestination = (limiterMaxConst as OneRegisterInstruction).registerA - - fun hexFloat(float: Float): String = "0x%08x".format(float.toRawBits()) - - limiterMethod.replaceInstruction( - limiterMinConstIndex, - "const/high16 v$limiterMinConstDestination, ${hexFloat(speedLimitMin)}" - ) - limiterMethod.replaceInstruction( - limiterMaxConstIndex, - "const/high16 v$limiterMaxConstDestination, ${hexFloat(speedLimitMax)}" - ) - - val constructorResult = VideoSpeedPatchFingerprint.result!! - val constructor = constructorResult.mutableMethod - val implementation = constructor.implementation!! - - val stepsGranularity = 8F - val step = speedLimitMax - .minus(speedLimitMin) // calculate the range of the speeds - .div(speedsGranularity) - .times(stepsGranularity) - .roundToInt() - .div(stepsGranularity)// round to nearest multiple of stepsGranularity - .coerceAtLeast(1 / stepsGranularity) // ensure steps are at least 1/8th of the step granularity - - val videoSpeedsArray = buildList { - DoubleStream - .iterate(speedLimitMin.toDouble()) { it + step } // create a stream of speeds - .let { speedStream -> - for (speed in speedStream) { - if (speed > speedLimitMax) break - add(speed.toFloat().toRawBits()) - } - } - } - - // adjust the new array of speeds size - constructor.replaceInstruction( - 0, - "const/16 v0, ${videoSpeedsArray.size}" - ) - - // create the payload with the new speeds - val arrayPayloadIndex = implementation.instructions.size - 1 - implementation.replaceInstruction( - arrayPayloadIndex, - BuilderArrayPayload( - 4, - videoSpeedsArray - ) - ) - - return PatchResultSuccess() - } - - companion object : OptionsContainer() { - private fun String?.validate(max: Int? = null) = this?.toFloatOrNull() != null && - toFloat().let { float -> - float > 0 && max?.let { max -> float <= max } ?: true - } - - val videoSpeedsGranularity by option( - PatchOption.StringOption( - "granularity", - "16", - "Video speed granularity", - "The granularity of the video speeds. The higher the value, the more speeds will be available.", - true - ) { - it.validate() - } - ) - - val minVideoSpeed by option( - PatchOption.StringOption( - "min", - "0.25", - "Minimum video speed", - "The minimum video speed.", - true - ) { - it.validate() - } - ) - - val maxVideoSpeed by option( - PatchOption.StringOption( - "max", - "5.0", - "Maximum video speed", - "The maximum video speed. Must be greater than the minimum video speed and smaller than 5.", - true - ) { - it.validate(5) - } - ) - } -} diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt deleted file mode 100644 index b2e78b8..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/annotation/VideoIdCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.video.videoid.annotation - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class VideoIdCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt deleted file mode 100644 index 2c7c4f9..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/fingerprint/VideoIdFingerprint.kt +++ /dev/null @@ -1,23 +0,0 @@ -package app.revanced.patches.youtube.misc.video.videoid.fingerprint - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.video.videoid.annotation.VideoIdCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode - -@Name("video-id-fingerprint") -@VideoIdCompatibility -@Version("0.0.1") -object VideoIdFingerprint : MethodFingerprint( - "V", - AccessFlags.DECLARED_SYNCHRONIZED or AccessFlags.FINAL or AccessFlags.PUBLIC, - listOf("L"), - listOf(Opcode.INVOKE_INTERFACE), - customFingerprint = { - it.definingClass.endsWith("PlaybackLifecycleMonitor;") - } -) diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt deleted file mode 100644 index da21078..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/videoid/patch/VideoIdPatch.kt +++ /dev/null @@ -1,58 +0,0 @@ -package app.revanced.patches.youtube.misc.video.videoid.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch -import app.revanced.patches.youtube.misc.video.videoid.annotation.VideoIdCompatibility -import app.revanced.patches.youtube.misc.video.videoid.fingerprint.VideoIdFingerprint -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Name("video-id-hook") -@Description("Hooks to detect when the video id changes") -@VideoIdCompatibility -@Version("0.0.1") -@DependsOn([IntegrationsPatch::class]) -class VideoIdPatch : BytecodePatch( - listOf( - VideoIdFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - with(VideoIdFingerprint.result!!) { - insertMethod = mutableMethod - insertIndex = scanResult.patternScanResult!!.endIndex + 2 - - videoIdRegister = (insertMethod.instruction(insertIndex - 1) as OneRegisterInstruction).registerA - } - - return PatchResultSuccess() - } - - companion object { - private var videoIdRegister = 0 - private var insertIndex = 0 - - private lateinit var insertMethod: MutableMethod - - /** - * Adds an invoke-static instruction, called with the new id when the video changes - * @param methodDescriptor which method to call. Params have to be `Ljava/lang/String;` - */ - fun injectCall( - methodDescriptor: String - ) = insertMethod.addInstructions( - insertIndex, // move-result-object offset - "invoke-static {v$videoIdRegister}, $methodDescriptor" - ) - } -} - diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt deleted file mode 100644 index 72caa0d..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/annotations/CustomVideoBufferCompatibility.kt +++ /dev/null @@ -1,13 +0,0 @@ -package app.revanced.patches.youtube.misc.videobuffer.annotations - -import app.revanced.patcher.annotation.Compatibility -import app.revanced.patcher.annotation.Package - -@Compatibility( - [Package( - "com.google.android.youtube", arrayOf("17.36.37", "17.41.37", "17.42.35", "17.43.36") - )] -) -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -internal annotation class CustomVideoBufferCompatibility diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/MaxBufferFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/MaxBufferFingerprint.kt deleted file mode 100644 index 81e8972..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/MaxBufferFingerprint.kt +++ /dev/null @@ -1,26 +0,0 @@ -package app.revanced.patches.youtube.misc.videobuffer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction - -@Name("maxbuffer-fingerprint") -@CustomVideoBufferCompatibility -@Version("0.0.1") -object MaxBufferFingerprint : MethodFingerprint( - "I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), - listOf(Opcode.SGET_OBJECT, Opcode.IGET, Opcode.IF_EQZ, Opcode.RETURN), - customFingerprint = { methodDef -> - methodDef.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;" - && methodDef.implementation!!.instructions.any { - ((it as? NarrowLiteralInstruction)?.narrowLiteral == 120000) - && methodDef.name == "r" - } - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/PlaybackBufferFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/PlaybackBufferFingerprint.kt deleted file mode 100644 index a080e19..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/PlaybackBufferFingerprint.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.revanced.patches.youtube.misc.videobuffer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction - -@Name("playbackbuffer-fingerprint") -@CustomVideoBufferCompatibility -@Version("0.0.1") -object PlaybackBufferFingerprint : MethodFingerprint( - "I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), - listOf(Opcode.IF_LEZ, Opcode.RETURN), - customFingerprint = { methodDef -> - methodDef.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;" - && methodDef.implementation!!.instructions.any { - ((it as? NarrowLiteralInstruction)?.narrowLiteral == 1600) - } - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/ReBufferFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/ReBufferFingerprint.kt deleted file mode 100644 index 3ca083f..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/fingerprints/ReBufferFingerprint.kt +++ /dev/null @@ -1,25 +0,0 @@ -package app.revanced.patches.youtube.misc.videobuffer.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.extensions.or - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility -import org.jf.dexlib2.AccessFlags -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.iface.instruction.NarrowLiteralInstruction - -@Name("playbackbuffer-fingerprint") -@CustomVideoBufferCompatibility -@Version("0.0.1") -object ReBufferFingerprint : MethodFingerprint( - "I", AccessFlags.PUBLIC or AccessFlags.FINAL, listOf(), - listOf(Opcode.IF_LEZ, Opcode.RETURN), - customFingerprint = { methodDef -> - methodDef.definingClass == "Lcom/google/android/libraries/youtube/innertube/model/media/PlayerConfigModel;" - && methodDef.implementation!!.instructions.any { - ((it as? NarrowLiteralInstruction)?.narrowLiteral == 5000) - } - } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt deleted file mode 100644 index 18587eb..0000000 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/videobuffer/patch/CustomVideoBufferPatch.kt +++ /dev/null @@ -1,137 +0,0 @@ -package app.revanced.patches.youtube.misc.videobuffer.patch - -import app.revanced.patcher.annotation.Description -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.instruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.patch.BytecodePatch -import app.revanced.patcher.patch.PatchResult -import app.revanced.patcher.patch.PatchResultSuccess -import app.revanced.patcher.patch.annotations.DependsOn -import app.revanced.patcher.patch.annotations.Patch -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.InputType -import app.revanced.patches.youtube.misc.settings.framework.components.impl.PreferenceScreen -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import app.revanced.patches.youtube.misc.settings.framework.components.impl.TextPreference -import app.revanced.patches.youtube.misc.videobuffer.annotations.CustomVideoBufferCompatibility -import app.revanced.patches.youtube.misc.videobuffer.fingerprints.MaxBufferFingerprint -import app.revanced.patches.youtube.misc.videobuffer.fingerprints.PlaybackBufferFingerprint -import app.revanced.patches.youtube.misc.videobuffer.fingerprints.ReBufferFingerprint -import org.jf.dexlib2.iface.instruction.OneRegisterInstruction - -@Patch -@Name("custom-video-buffer") -@Description("Lets you change the buffers of videos.") -@DependsOn([SettingsPatch::class]) -@CustomVideoBufferCompatibility -@Version("0.0.1") -class CustomVideoBufferPatch : BytecodePatch( - listOf( - MaxBufferFingerprint, PlaybackBufferFingerprint, ReBufferFingerprint - ) -) { - override fun execute(context: BytecodeContext): PatchResult { - SettingsPatch.PreferenceScreen.MISC.addPreferences( - PreferenceScreen( - "revanced_custom_video_buffer", - StringResource("revanced_custom_video_buffer_title", "Video buffer settings"), - listOf( - TextPreference( - "revanced_pref_max_buffer_ms", - StringResource("revanced_pref_max_buffer_ms_title", "Maximum buffer size"), - InputType.NUMBER, - "120000", - StringResource( - "revanced_pref_max_buffer_ms_summary", - "The maximum size of a buffer for playback" - ) - ), - TextPreference( - "revanced_pref_buffer_for_playback_ms", - StringResource("revanced_pref_buffer_for_playback_ms_title", "Maximum buffer for playback"), - InputType.NUMBER, - "2500", - StringResource( - "revanced_pref_buffer_for_playback_ms_summary", - "Maximum size of a buffer for playback" - ) - ), - TextPreference( - "revanced_pref_buffer_for_playback_after_rebuffer_ms", - StringResource( - "revanced_pref_buffer_for_playback_after_rebuffer_ms_title", - "Maximum buffer for playback after rebuffer" - ), - InputType.NUMBER, - "5000", - StringResource( - "revanced_pref_buffer_for_playback_after_rebuffer_ms_summary", - "Maximum size of a buffer for playback after rebuffering" - ) - ) - ), - StringResource("revanced_custom_video_buffer_summary", "Custom settings for video buffer") - ) - ) - - execMaxBuffer() - execPlaybackBuffer() - execReBuffer() - return PatchResultSuccess() - } - - private fun execMaxBuffer() { - val (method, result) = MaxBufferFingerprint.unwrap(true, -1) - val (index, register) = result - - method.addInstructions( - index + 1, """ - invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getMaxBuffer()I - move-result v$register - """ - ) - } - - private fun execPlaybackBuffer() { - val (method, result) = PlaybackBufferFingerprint.unwrap() - val (index, register) = result - - method.addInstructions( - index + 1, """ - invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getPlaybackBuffer()I - move-result v$register - """ - ) - } - - private fun execReBuffer() { - val (method, result) = ReBufferFingerprint.unwrap() - val (index, register) = result - - method.addInstructions( - index + 1, """ - invoke-static {}, Lapp/revanced/integrations/patches/VideoBufferPatch;->getReBuffer()I - move-result v$register - """ - ) - } - - private fun MethodFingerprint.unwrap( - forEndIndex: Boolean = false, - offset: Int = 0 - ): Pair> { - val result = this.result!! - val method = result.mutableMethod - val scanResult = result.scanResult.patternScanResult!! - val index = (if (forEndIndex) scanResult.endIndex else scanResult.startIndex) + offset - - val register = (method.instruction(index) as OneRegisterInstruction).registerA - - return method to (index to register) - } -} diff --git a/src/main/kotlin/app/revanced/shared/fingerprints/WatchWhileActivityFingerprint.kt b/src/main/kotlin/app/revanced/shared/fingerprints/WatchWhileActivityFingerprint.kt deleted file mode 100644 index 24256f1..0000000 --- a/src/main/kotlin/app/revanced/shared/fingerprints/WatchWhileActivityFingerprint.kt +++ /dev/null @@ -1,17 +0,0 @@ -package app.revanced.shared.fingerprints - -import app.revanced.patcher.annotation.Name -import app.revanced.patcher.annotation.Version - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patches.youtube.interaction.swipecontrols.annotation.SwipeControlsCompatibility - -@Name("watch-while-activity-fingerprint") - -@SwipeControlsCompatibility -@Version("0.0.1") -object WatchWhileActivityFingerprint : MethodFingerprint( - customFingerprint = { methodDef -> - methodDef.definingClass.endsWith("WatchWhileActivity;") && methodDef.name == "" - } -) diff --git a/src/main/kotlin/app/revanced/util/microg/Constants.kt b/src/main/kotlin/app/revanced/util/microg/Constants.kt deleted file mode 100644 index 912b975..0000000 --- a/src/main/kotlin/app/revanced/util/microg/Constants.kt +++ /dev/null @@ -1,130 +0,0 @@ -package app.revanced.util.microg - -/** - * constants for microG builds with signature spoofing - */ -internal object Constants { - /** - * microG vendor name - * aka. package prefix / package base - */ - const val MICROG_VENDOR = "com.mgoogle" - - /** - * meta-data for microG package name spoofing on patched builds - */ - const val META_SPOOFED_PACKAGE_NAME = "$MICROG_VENDOR.android.gms.SPOOFED_PACKAGE_NAME" - - /** - * meta-data for microG package signature spoofing on patched builds - */ - const val META_SPOOFED_PACKAGE_SIGNATURE = "$MICROG_VENDOR.android.gms.SPOOFED_PACKAGE_SIGNATURE" - - /** - * meta-data for microG package detection - */ - const val META_GMS_PACKAGE_NAME = "app.revanced.MICROG_PACKAGE_NAME" - - /** - * a list of all permissions in microG - */ - val PERMISSIONS = listOf( - // C2DM / GCM - "com.google.android.c2dm.permission.RECEIVE", - "com.google.android.c2dm.permission.SEND", - "com.google.android.gtalkservice.permission.GTALK_SERVICE", - - // GAuth - "com.google.android.googleapps.permission.GOOGLE_AUTH", - "com.google.android.googleapps.permission.GOOGLE_AUTH.cp", - "com.google.android.googleapps.permission.GOOGLE_AUTH.local", - "com.google.android.googleapps.permission.GOOGLE_AUTH.mail", - "com.google.android.googleapps.permission.GOOGLE_AUTH.writely", - ) - - /** - * a list of all (intent) actions in microG - */ - val ACTIONS = listOf( - // location - "com.google.android.gms.location.places.ui.PICK_PLACE", - "com.google.android.gms.location.places.GeoDataApi", - "com.google.android.gms.location.places.PlacesApi", - "com.google.android.gms.location.places.PlaceDetectionApi", - "com.google.android.gms.wearable.MESSAGE_RECEIVED", - - // C2DM / GCM - "com.google.android.c2dm.intent.REGISTER", - "com.google.android.c2dm.intent.REGISTRATION", - "com.google.android.c2dm.intent.UNREGISTER", - "com.google.android.c2dm.intent.RECEIVE", - "com.google.iid.TOKEN_REQUEST", - "com.google.android.gcm.intent.SEND", - - // car - "com.google.android.gms.car.service.START", - - // people - "com.google.android.gms.people.service.START", - - // wearable - "com.google.android.gms.wearable.BIND", - - // auth - "com.google.android.gsf.login", - "com.google.android.gsf.action.GET_GLS", - "com.google.android.gms.common.account.CHOOSE_ACCOUNT", - "com.google.android.gms.auth.login.LOGIN", - "com.google.android.gms.auth.api.credentials.PICKER", - "com.google.android.gms.auth.api.credentials.service.START", - "com.google.android.gms.auth.service.START", - "com.google.firebase.auth.api.gms.service.START", - "com.google.android.gms.auth.be.appcert.AppCertService", - - // fido - "com.google.android.gms.fido.fido2.privileged.START", - - // games - "com.google.android.gms.games.service.START", - "com.google.android.gms.games.PLAY_GAMES_UPGRADE", - - // chimera - "com.google.android.gms.chimera", - - // fonts - "com.google.android.gms.fonts", - - // phenotype - "com.google.android.gms.phenotype.service.START", - - // location - "com.google.android.gms.location.reporting.service.START", - - // misc - "com.google.android.gms.gmscompliance.service.START", - "com.google.android.gms.oss.licenses.service.START", - "com.google.android.gms.safetynet.service.START", - "com.google.android.gms.tapandpay.service.BIND" - ) - - /** - * a list of all content provider authorities in microG - */ - val AUTHORITIES = listOf( - // gsf - "com.google.android.gsf.gservices", - "com.google.settings", - - // auth - "com.google.android.gms.auth.accounts", - - // chimera - "com.google.android.gms.chimera", - - // fonts - "com.google.android.gms.fonts", - - // phenotype - "com.google.android.gms.phenotype" - ) -} diff --git a/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt b/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt deleted file mode 100644 index b4b4038..0000000 --- a/src/main/kotlin/app/revanced/util/microg/MicroGBytecodeHelper.kt +++ /dev/null @@ -1,241 +0,0 @@ -package app.revanced.util.microg - -import app.revanced.patcher.data.BytecodeContext -import app.revanced.patcher.extensions.addInstruction -import app.revanced.patcher.extensions.addInstructions -import app.revanced.patcher.extensions.replaceInstruction -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import app.revanced.patcher.util.proxy.mutableTypes.MutableClass -import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod -import app.revanced.util.microg.Constants.ACTIONS -import app.revanced.util.microg.Constants.AUTHORITIES -import app.revanced.util.microg.Constants.MICROG_VENDOR -import app.revanced.util.microg.Constants.PERMISSIONS -import org.jf.dexlib2.Opcode -import org.jf.dexlib2.builder.instruction.BuilderInstruction21c -import org.jf.dexlib2.iface.instruction.formats.Instruction21c -import org.jf.dexlib2.iface.reference.StringReference -import org.jf.dexlib2.immutable.reference.ImmutableStringReference - -/** - * Helper class for applying bytecode patches needed for the microg-support patches. - */ -internal object MicroGBytecodeHelper { - /** - * Hook a method to check the availability of MicroG. - * - * @param fingerprint The fingerprint of the method to add the call for the notice in. - */ - fun injectNotice(fingerprint: MethodFingerprint) { - fingerprint.result!!.mutableMethod.addInstruction( - 0, - "invoke-static {}, Lapp/revanced/integrations/patches/MicroGSupport;->checkAvailability()V" - ) - } - - /** - * Transform strings with package name out of [fromPackageName] and [toPackageName]. - * - * @param fromPackageName Original package name. - * @param toPackageName The package name to accept. - **/ - fun packageNameTransform(fromPackageName: String, toPackageName: String): (String) -> String? { - return { referencedString -> - when (referencedString) { - "$fromPackageName.SuggestionsProvider", - "$fromPackageName.fileprovider" -> referencedString.replace(fromPackageName, toPackageName) - else -> null - } - } - } - - /** - * Prime method data class for the [MicroGBytecodeHelper] class. - * - * @param primeMethodFingerprint The prime methods [MethodFingerprint]. - * @param fromPackageName Original package name. - * @param toPackageName The package name to accept. - **/ - data class PrimeMethodTransformationData( - val primeMethodFingerprint: MethodFingerprint, - val fromPackageName: String, - val toPackageName: String - ) { - /** - * Patch the prime method to accept the new package name. - */ - fun transformPrimeMethodPackageName() { - val primeMethod = primeMethodFingerprint.result!!.mutableMethod - val implementation = primeMethod.implementation!! - - var register = 2 - val index = implementation.instructions.indexOfFirst { - if (it.opcode != Opcode.CONST_STRING) return@indexOfFirst false - - val instructionString = ((it as Instruction21c).reference as StringReference).string - if (instructionString != fromPackageName) return@indexOfFirst false - - register = it.registerA - return@indexOfFirst true - } - - primeMethod.replaceInstruction( - index, "const-string v$register, \"$toPackageName\"" - ) - } - } - - /** - * Patch the bytecode to work with MicroG. - * Note: this only handles string constants to gms (intent actions, authorities, ...). - * If the app employs additional checks to validate the installed gms package, you'll have to handle those in the app- specific patch - * - * @param context The context. - * @param additionalStringTransforms Additional transformations applied to all const-string references. - * @param primeMethodTransformationData Data to patch the prime method. - * @param earlyReturns List of [MethodFingerprint] to return the resolved methods early. - */ - fun patchBytecode( - context: BytecodeContext, - additionalStringTransforms: Array<(str: String) -> String?>, - primeMethodTransformationData: PrimeMethodTransformationData, - earlyReturns: List - ) { - earlyReturns.returnEarly() - primeMethodTransformationData.transformPrimeMethodPackageName() - - val allTransforms = arrayOf( - MicroGBytecodeHelper::commonTransform, - MicroGBytecodeHelper::contentUrisTransform, - *additionalStringTransforms - ) - - // transform all strings using all provided transforms, first match wins - context.transformStringReferences transform@{ - for (transformFn in allTransforms) { - val s = transformFn(it) - if (s != null) return@transform s - } - - return@transform null - } - } - - /** - * const-string transform function for common gms string references. - * - * @param referencedString The string to transform. - */ - private fun commonTransform(referencedString: String): String? = - when (referencedString) { - "com.google", - "com.google.android.gms", - in PERMISSIONS, - in ACTIONS, - in AUTHORITIES -> referencedString.replace("com.google", MICROG_VENDOR) - - // subscribedfeeds has no vendor prefix for whatever reason... - "subscribedfeeds" -> "${MICROG_VENDOR}.subscribedfeeds" - else -> null - } - - - /** - * const-string transform function for strings containing gms content uris / authorities. - */ - private fun contentUrisTransform(str: String): String? { - // only when content:// uri - if (str.startsWith("content://")) { - // check if matches any authority - for (authority in AUTHORITIES) { - val uriPrefix = "content://$authority" - if (str.startsWith(uriPrefix)) { - return str.replace( - uriPrefix, - "content://${authority.replace("com.google", MICROG_VENDOR)}" - ) - } - } - - // gms also has a 'subscribedfeeds' authority, check for that one too - val subFeedsUriPrefix = "content://subscribedfeeds" - if (str.startsWith(subFeedsUriPrefix)) { - return str.replace(subFeedsUriPrefix, "content://${MICROG_VENDOR}.subscribedfeeds") - } - } - - return null - } - - /** - * Transform all constant string references using a transformation function. - * - * @param transformFn string transformation function. if null, string is not changed. - */ - private fun BytecodeContext.transformStringReferences(transformFn: (str: String) -> String?) { - classes.forEach { classDef -> - var mutableClass: MutableClass? = null - - // enumerate all methods - classDef.methods.forEach classLoop@{ methodDef -> - var mutableMethod: MutableMethod? = null - val implementation = methodDef.implementation ?: return@classLoop - - // enumerate all instructions and find const-string - implementation.instructions.forEachIndexed implLoop@{ index, instruction -> - // skip all that are not const-string - if (instruction.opcode != Opcode.CONST_STRING) return@implLoop - val str = ((instruction as Instruction21c).reference as StringReference).string - - // call transform function - val transformedStr = transformFn(str) - if (transformedStr != null) { - // make class and method mutable, if not already - mutableClass = mutableClass ?: proxy(classDef).mutableClass - mutableMethod = mutableMethod ?: mutableClass!!.methods.first { - it.name == methodDef.name && it.parameterTypes.containsAll(methodDef.parameterTypes) - } - - // replace instruction with updated string - mutableMethod!!.implementation!!.replaceInstruction( - index, - BuilderInstruction21c( - Opcode.CONST_STRING, - instruction.registerA, - ImmutableStringReference( - transformedStr - ) - ) - ) - } - } - } - } - } - - /** - * Return the resolved methods of a list of [MethodFingerprint] early. - */ - private fun List.returnEarly() { - this.forEach { fingerprint -> - val result = fingerprint.result!! - val stringInstructions = when (result.method.returnType.first()) { - 'L' -> """ - const/4 v0, 0x0 - return-object v0 - """ - - 'V' -> "return-void" - 'I' -> """ - const/4 v0, 0x0 - return v0 - """ - - else -> throw Exception("This case should never happen.") - } - result.mutableMethod.addInstructions( - 0, stringInstructions - ) - } - } -} diff --git a/src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt b/src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt deleted file mode 100644 index 003fa00..0000000 --- a/src/main/kotlin/app/revanced/util/microg/MicroGManifestHelper.kt +++ /dev/null @@ -1,58 +0,0 @@ -package app.revanced.util.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.util.microg.Constants.META_GMS_PACKAGE_NAME -import app.revanced.util.microg.Constants.META_SPOOFED_PACKAGE_NAME -import app.revanced.util.microg.Constants.META_SPOOFED_PACKAGE_SIGNATURE -import app.revanced.util.microg.Constants.MICROG_VENDOR -import org.w3c.dom.Element -import org.w3c.dom.Node - -/** - * helper class for adding manifest metadata needed for microG builds with signature spoofing - */ -internal object MicroGManifestHelper { - - /** - * Add manifest entries needed for package and signature spoofing when using MicroG. - * Note: this only adds metadata entries for signature spoofing, other changes may still be required to make a microG patch work. - * - * @param context Resource context. - * @param spoofedPackage The package to spoof. - * @param spoofedSignature The signature to spoof. - */ - fun addSpoofingMetadata( - context: ResourceContext, - spoofedPackage: String, - spoofedSignature: String - ) { - context.xmlEditor["AndroidManifest.xml"].use { - val applicationNode = it - .file - .getElementsByTagName("application") - .item(0) - - // package spoofing - applicationNode.adoptChild("meta-data") { - setAttribute("android:name", META_SPOOFED_PACKAGE_NAME) - setAttribute("android:value", spoofedPackage) - } - applicationNode.adoptChild("meta-data") { - setAttribute("android:name", META_SPOOFED_PACKAGE_SIGNATURE) - setAttribute("android:value", spoofedSignature) - } - - // microG presence detection in integrations - applicationNode.adoptChild("meta-data") { - setAttribute("android:name", META_GMS_PACKAGE_NAME) - setAttribute("android:value", "${MICROG_VENDOR}.android.gms") - } - } - } - - private fun Node.adoptChild(tagName: String, block: Element.() -> Unit) { - val child = ownerDocument.createElement(tagName) - child.block() - appendChild(child) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt b/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt deleted file mode 100644 index 6c8af52..0000000 --- a/src/main/kotlin/app/revanced/util/microg/MicroGResourceHelper.kt +++ /dev/null @@ -1,59 +0,0 @@ -package app.revanced.util.microg - -import app.revanced.patcher.data.ResourceContext -import app.revanced.util.resources.ResourceUtils.Settings.mergeStrings - -/** - * Helper class for applying resource patches needed for the microg-support patches. - */ -internal object MicroGResourceHelper { - - /** - * Add necessary strings to the strings.xml file. - * - * @param context The resource context. - * @param stringsHost The file which hosts the strings. - */ - fun addStrings(context: ResourceContext, stringsHost: String = "microg/host/values/strings.xml") = context.mergeStrings(stringsHost) - - /** - * Patch the manifest to work with MicroG. - * - * @param context The resource context. - * @param fromPackageName The original package name. - * @param toPackageName The package name to accept. - * @param toName The new name of the app. - */ - fun patchManifest( - context: ResourceContext, - fromPackageName: String, - toPackageName: String, - toName: String - ) { - val manifest = context["AndroidManifest.xml"].readText() - context["AndroidManifest.xml"].writeText( - manifest.replace( - "package=\"$fromPackageName", - "package=\"$toPackageName" - ).replace( - "android:label=\"@string/app_name", - "android:label=\"$toName" - ).replace( - "android:label=\"@string/app_launcher_name", - "android:label=\"$toName" - ).replace( - "android:authorities=\"$fromPackageName", - "android:authorities=\"$toPackageName" - ).replace( - "$fromPackageName.permission.C2D_MESSAGE", - "$toPackageName.permission.C2D_MESSAGE" - ).replace( - "com.google.android.c2dm", - "${Constants.MICROG_VENDOR}.android.c2dm" - ).replace( - "", - "" - ) - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt b/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt deleted file mode 100644 index c160e78..0000000 --- a/src/main/kotlin/app/revanced/util/resources/ResourceUtils.kt +++ /dev/null @@ -1,104 +0,0 @@ -package app.revanced.util.resources - -import app.revanced.patcher.data.DomFileEditor -import app.revanced.patcher.data.ResourceContext -import app.revanced.patches.youtube.misc.settings.bytecode.patch.SettingsPatch -import app.revanced.patches.youtube.misc.settings.framework.components.impl.StringResource -import org.w3c.dom.Node -import java.nio.file.Files -import java.nio.file.StandardCopyOption - -internal object ResourceUtils { - - /** - * Settings related utilities - */ - internal object Settings { - /** - * Merge strings. This handles [StringResource]s automatically. - * @param host The hosting xml resource. Needs to be a valid strings.xml resource. - */ - internal fun ResourceContext.mergeStrings(host: String) { - this.iterateXmlNodeChildren(host, "resources") { - // TODO: figure out why this is needed - if (!it.hasAttributes()) return@iterateXmlNodeChildren - - val attributes = it.attributes - val key = attributes.getNamedItem("name")!!.nodeValue!! - val value = it.textContent!! - - val formatted = attributes.getNamedItem("formatted") == null - - SettingsPatch.addString(key, value, formatted) - } - } - } - - /** - * Copy resources from the current class loader to the resource directory. - * @param sourceResourceDirectory The source resource directory name. - * @param resources The resources to copy. - */ - internal fun ResourceContext.copyResources(sourceResourceDirectory: String, vararg resources: ResourceGroup) { - val classLoader = ResourceUtils.javaClass.classLoader - val targetResourceDirectory = this["res"] - - for (resourceGroup in resources) { - resourceGroup.resources.forEach { resource -> - val resourceFile = "${resourceGroup.resourceDirectoryName}/$resource" - Files.copy( - classLoader.getResourceAsStream("$sourceResourceDirectory/$resourceFile")!!, - targetResourceDirectory.resolve(resourceFile).toPath(), StandardCopyOption.REPLACE_EXISTING - ) - } - } - } - - /** - * Resource names mapped to their corresponding resource data. - * @param resourceDirectoryName The name of the directory of the resource. - * @param resources A list of resource names. - */ - internal class ResourceGroup(val resourceDirectoryName: String, vararg val resources: String) - - /** - * Iterate through the children of a node by its tag. - * @param resource The xml resource. - * @param targetTag The target xml node. - * @param callback The callback to call when iterating over the nodes. - */ - internal fun ResourceContext.iterateXmlNodeChildren( - resource: String, - targetTag: String, - callback: (node: Node) -> Unit - ) = - xmlEditor[ResourceUtils.javaClass.classLoader.getResourceAsStream(resource)!!].use { - val stringsNode = it.file.getElementsByTagName(targetTag).item(0).childNodes - for (i in 1 until stringsNode.length - 1) callback(stringsNode.item(i)) - } - - - /** - * Copies the specified node of the source [DomFileEditor] to the target [DomFileEditor]. - * @param source the source [DomFileEditor]. - * @param target the target [DomFileEditor]- - * @return AutoCloseable that closes the target [DomFileEditor]s. - */ - fun String.copyXmlNode(source: DomFileEditor, target: DomFileEditor): AutoCloseable { - val hostNodes = source.file.getElementsByTagName(this).item(0).childNodes - - val destinationResourceFile = target.file - val destinationNode = destinationResourceFile.getElementsByTagName(this).item(0) - - for (index in 0 until hostNodes.length) { - val node = hostNodes.item(index).cloneNode(true) - destinationResourceFile.adoptNode(node) - destinationNode.appendChild(node) - } - - return AutoCloseable { - source.close() - target.close() - } - } -} \ No newline at end of file diff --git a/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_background_color_108.png deleted file mode 100644 index e2dc8a53f7a24daf917c9ba172fe8ed23aa01881..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3044 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 F0svGsm-GMt diff --git a/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-hdpi/adaptiveproduct_youtube_foreground_color_108.png deleted file mode 100644 index e5a73b561046813b12ad77b27f4af7b3ec0b7bca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5129 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 diff --git a/src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index dc967b7703117197f110db919bb390ea5d40cbb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4571 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 diff --git a/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png b/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_background_color_108.png deleted file mode 100644 index 4dee1752a39cdc6a0cf032128945586b6720a2d6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2937 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 diff --git a/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-mdpi/adaptiveproduct_youtube_foreground_color_108.png deleted file mode 100644 index 3d26f5b2b3f61baabc12a4b7e02b04623c408442..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4366 zcmeAS@N?(olHy`uVBq!ia0y~yV8{Vs4mJh`hW@nhvkVLjoCO|{#S9EAejv=~)IIqR z0|S?Trn7TEKt_H^esM;Afr6*AvqC{pep+TuDg#5st+~PJA;B-jY`@?8;^f`YFvUAR zNR&e%$f>(QWTKjuBBy{?hvLGUqJakmU0qqEPb}zQ?(1vl5e?Mg>EgP<{zP$6U-ROQ zu2a7sRxi%Jw&(k^v;VeUw|lQz`~GlIyvbvLx3(rf_nY4%M1;3f6T0AWQd-kD9X5C zB7=f(YKIF$hBd>Q^I=`C3=swlB5B@7EE#U-G8lMT#JFBV&*2Bohp{DjnN#sh3w(sdU6`)JjJy| z%o3RrXF2E{s+=il)M�PV*|l=S%D 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�PV*|l=S%D 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�PV*|l=S%D z)AOqf92giLmegJRr=!1Fs==DAA@|=R)pslzaoh_^zjvo?;&<4}u;Asb@XrOHuyI{D zVdu@8PoF%w;dR6*I`LF^?Z5Ox@dv{H=KQR)`SbnjgME)w8jWHb-C2G-ICSQV&r+H5 zlQ>(F?mX*v|FfO@{~y`QN=H1Cc1CE4JPs5p>~opb^Vw*rQm4}-&7-Q9{-->;uk)MP z?!GC*hAcbA>WR85Vw0J_d8-RVlpJ{Uoq^%g?)-ySG&qj}HTE=evN)dL5KdIQ z)xnt56`|b6AwIM9hvGpG7NKqxg_9j3flA&JO+5^QxN*)_l1-a!&&`e3ua#^+9GA!W47@5h1D7SxBBgz zj~g6#A;E5ZB*#GS*kPxQ7CM}hlTU9{TEnyYnAC=_HO#v^zb2pGSk5BU=z4(DjHTR3 zAyLlJBf=-b?}o<;1sN3+!CRc>oXjnOht!oOukhZYwoCBm5s4%t!}bUd9p!66{lfYJ z)g8`9%vFRsosHCYPGIufxFqC~&?UD^c|poAbym(c@sLuUeDYRG_9k}ADLM+;Ct9D( zeRBAT@e}DMil3sn<|a85F8LAsNF(S}mY3vHfu|-<*-~d1IfgEt6?AvS!Vp2z{wSxl z3%3QW4{To{Y*ISQ@@%u1r}xsei>6+d$`H@^p1J--$u7aWQ|0`oUkJZ+`lb7e=`WbS zl=JYmi8deaNY{{@Ex|64E?F+IeumF7$;;i6$3qOv4PVcAK9hfDerSZ&Hmw@biKn=x zdQDZEDy^j-vU1h3RrgkLhkgz{9n!xtF1U7`Tc~mHe>d_u9`{m@QFl-8KgT-vdGO8PyUV$j zi}~7GeO;%wDtoE)!rd*_s-Zv4yNvdDMa_T;rjSw=362#t!}?6!99TGea2*X~{}xO}JIWWUw(uB9K| z@NwJ8Z7a7+Zg_fw?e@BDx!Y zH{DKew)C;PC-y$^D*0L%`>^WL*SWJd&pz~a#qIU)%-&_bYrix9jLCe>d6CA&7Y?6r zeh~QdqCNNgsRr5i*VOqt`!}Xte?weiF{Ks~WZOrc( z-HVJrV}4-!iS4KT59iN|Z@uqaulzsdf7Sns49go-8Pl0N8yy>?nSTGMs!`nEXK!^o z_1mVKZykFU>~s`$>~C7z^z`6b#f%egCahKb{(Q!{iRUu;S_A4{T)V)Y_$;yea2=0& zYkO;Wn|)tFM}*Wx!|A5w7w~uqa%k{cmrdoEZ^s;PjneQ^$Wq(XB zE%MCOh`AA-Io>jsdRptu@^bdw|MT{9`=hy!xF1)G&(J>+TTr?1+@UY6%f(je3F%l( zbMWc#vzYS1Q9x^jSdZ!_;d0eJuF6BQhtiewFPdHKxZxb5CFl3aL(8{n(wm8UOe9?^Mp05k-A*loR+-^iPE^P#l9&$H9T$q+0Ijz(^k*ZKKu5}=2N#P zn9q4X|NmQ|LqZQHZCl#r9j+@I@oev!EXz$cg_XCt9*eSSw}r8-vDwkJO)K}R|LV8l z)7RDQRjcyNZj3v4s_EcX#_ZSJpLO=5U*2G_JbEWM>JG<72+!miM zT7N_1PQ_E{_WV=(XWp5zW##H4J5$c5T}pfT?4IttXufHyrazm`m&bea))wCTVO!pQ z{pNaGfBIRC+q;{$IqzJ&-)6_2)a577owc?PSrYOkt)mB z$?2cY_spF-x3*62=bePxi?&riPd;})i$DMUE`gGVmt6mMKeygveJhIR>@!u2w#o?{vP3ODqSM8(!-MR7pPJPya z@&%tS-f{oV*4ljj-^8!|{LZZXGy6}s@wUC5XJKb)`N+QL@5?{SozJJ7SDPpPZ_&Tg z>%_(M>wa8)ef`|U85b8$|1^E_{@j|Se_tJVExG>ou|vn?_MNOSHjMic_WSL@@;l|S z?-$?a_kU8OP_OYn*4_6YK2V5m}MU}$J& zVEFl;fuZ3g14F3+1H-EX1_rAc3=HD=lj4uMF)*-HdAc};RNQ(q^R&NoxX7{kI+iBR zkQLGi%LJ!RIOUw>((oySfzfZ3mi4N4yUwUh-Iei4y=1D+VK&WFZquBG9c|ZEOmSC8 zWuDSh;h`xvyH%4rXVr}E=}O5Jn0 z^`%w3JypPp+7FoiWrCd6HCYER2m@wV8ugx{AT zAap6;4)zkppKQzDGBP{#FJpavkDDPhG^^pbgZHdJ14f$*TOQQ7F|1fsBwE38hdn1< z53JZ2g9GUIfPF2Z%BM_%yRBY)(7jBu`;LgIfPCvdJyhl`TU3wiMbk6?2zQnWCr?{IuKn zj9J*G%i`{u*St7v%^vN!n|C~~e(kAgkCKn~@k;AW@7}Y=M)`ZM@2`Y9_9wj7zxB97 zLqmCZd5bG5PL$8DKm9i&{M7&dGp?TY@BX_ZM(@<=)17Y0Ze@$&E;kjQtSMbKqvU+Y zv!h2{ofZnTwzkIn|784T-~UOvmp@*A?YlH3HFaSoAcIKGv`^oN_(+$TpwcTwQi{_6i&O*^CqPYmImoT#ytI=Td$NeiZveo4JjZIBmHAIYNPn0^#pkchawxB>jktJ{Y?0Zi|=Nz@p zZxdSf{e5WO{e8^>O^uBGQ>R3wu{msvd|UTF|INF1K_MY6pC9|ry!Ds8UFz7vwwb@m zyItmad3tg_ESS;R$*IlIb(UdATG;P{2N~nmiz~9sohxf2TfLdt|9Dx!?z31q7jE6^5@>q(aN+0mosAu$sjpwZ zUbA*>U{utpv$L<({69RO;mWnJ;DCSwmo5oKM@NU%_RhH3I3ZL!?!9qI?DDm1-~Nbn zcURxF?(tVU@AQq%X$)(kwi?;l`RRx)Ub(XK&6}K}qN0q973uZ$_g_8qeR(;PA#F`m zr`uv5zkiNpWoD(NUro%-i=TRl)$N}jp)-xILDHDvnd;X>&l)@VUF$C2yH_V;XLn!! zrNw^rS|c`xNq)>>Yjt&XH}2i*TUu&5b?Vfdyu3{tH%{bhXuRC9A>^w=|5GiMi3vG5 zBC*#mmd?Ex7{BZ0rsG+z-*$&SI`yz%!tB}JN)r{NdMCNbCpleiS{tUliG9-=W8IGx zbN24FRhsBwbxwT=|Fy2F$nLVw|CaoYow8Uk?9sxMGe)}Hm&&TPbUo2}@3l!YSZIpK zJ4}r;Fna-R}9C&vQ4QXFtHfGtI*|(6oVPrIVcCgXZH$jy-&$=g`Qd zQotaExux3<0_f3F`IFE;BUD{V}teks*4DqA25n zi3|$DsU0p18P*JI&WClmGDH|Kh@^QRv1GWR%V6Lcp60=@VLQWta{}C(7&v$s3<5h^ zH5pi{84^w?D_1bI%w!O8`xI{TQG1=hb1epjikX{icB)vqHb!&k7P5zj>&a=H^Ay(> zF-v4hoaLZ*sB)&HQKJd}gU@Fe7#2(v6@1YA`ESKJzIEr$ne}bsi`RX%pY6X=Qqtpp zPtUI|aA06~SW!-AK$!ao;)!p3#s zgq=5UK7I1!hSw3N=)_auwg1u&#UBX&oAa~I=Fj)95B5D$X*7y$bZ7bT;Lw>bK1*fJ zPvUGzy7R2x{m*vp|9@mJD;@Dn+8LoG@;Feau+L>y&u62hN}W!VG>@uY`k(UXzRquE zyZfdL8?x*et0(HNh)rhx=B+LeQF7qXcLs(}yYmlT(coZi$Y_3ezWo1t`@ilBR2dr5 zJSP=0FvPj2=!KlxY=4}Cfx%@#qt*sT=`RN*bPlk|9Av$7ko!-9S&Ng(kwZ=bPFyJs zGDQiRYnq%i+Rko})k@I6;vj2sATXnCasi*-q0k+CwgvpZ5;^7_)Y#L=$>Ml|LpV|K zRtIBJSA=pOhxp9aABqP(ScJM&6i#-C1S)w?H1#kH>IzW^^^pB!Tf}799^kJ-ZK7glHR-|Dw> zK5lT}g#^3tksJfPV~3qKTIg_2PCmU+X${ZnV^SN!)-dnx{F;1zV>ydZqw4`qGnR5E zg+w_=j|iU#zZ)Ja6l7FP1aEPgb27IC9#U7Dyuy2n+AhJLME}D8-DnmTud*=EVCA$RgPL=bUej)tQ>6h*=roUkR zQqIHMCfaNQnusv-zs_doG3wOJe@6TKQZpOTQaSii)@|WMM-242OOs)RkkiWUVmVb5UiD28z zqr!HZ=bVJiQPaYF8(ID1w?76t#~yZYUYa;Har(oSi90XaEWYa2>&D-cc`W9!%H!N) zxyKf(v8gGldHcTdeK#w}cjq$AW!65{KF80VIlJiWwV9@~Z4Iv*J)ix2_VwBKwv291H=cXr7%Oc-x+mqKCWf{3NA~Y&?v)kIaYgMo9Ub}m_;PRb*ll@lDyOw@< z!^dqWx2@bRx#8&zw%hBrnRA0@Uv^IyPv2SG{JEpM)4S=k z-gG;?+0w`Ep4j`utK@58?8B-{U+2!=Jp0hw6}Q*FGkcf$uKmvZGbZyj=S3P9UpRci z`9a{*i}u{}ry6A6UsLDr?BAHa^|`Wsvi`*IwbwUnUs}HEd*XX>yKiziwlTkF zbT2agjQN4>C$^vVKb$`=zV*Iyz4HH*|5g7lGAwUUWlU%8Y;S?Vr%gfn!|Igdc?T_X@;(lB$K12URY(eG1bBDgPE*D#=C!}LF z&B3R`&tl34M**!BVm+##gv(X?xGE3H9!gizzi4)`CP7Ql@s>(@cP`HZ8cA9R+&Psk*(EU!{$j7ClorZQuLj?E&Wycv$V3)Yf@V` z{X3f1yPFp=s`|R5@n@`=I zU_R&l{Qqx-4hcP+v~6jdcet)>#IwC?vMe{*6jt8mdMwJS-4@2S#%4#?Hm%&N{;S`H zPhVHJSFOr7yD{$IsiuQl8M9w=hjKk_t$lsx`rBCl2>rmX)iI>`XbIb}8-UvwOPpqWPw+n*MA$UmowxTU&VVhi!TL z^_%N${pn{lZtrg1=Dc(9ew!V8QkS1Rch=fIWJ$=EkY6EY?=Iclnt1(3-oR2DUt<2tuFSXX z`pzp?WiQ!=1odCje(lb8Tz=obx$nz$dCho3d*>W`q+H-q`Q+ty&imixc&%=g^;EBU z$bMPAOg3FsKg(&>r&(^ZgJ=DYPKw^;f5z_OwO9A5{1XyJxN28I!&9UDe*L)oI^fO3yPtclXQQ%8z3IuU(yI zX?u6?=c@egN56l)FLt-CNd51*)4Ok$tG`>j$A3@!7l*fwH=XacU$u|^cjw0YJM~!y z$`^dTc*p%aTWj03=E|P3=FRl7#OT(FffScPl`Y4#=yWh-_yl0q~g|_ON^Wh3>++mTaSHz zpULC6jpKOfq^4|TMmHAaBo_lEk|_y6_o0{{R3 diff --git a/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-xhdpi/adaptiveproduct_youtube_foreground_color_108.png deleted file mode 100644 index 4f66f60a390fdd50e21de67c28f54cf93571abf0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6199 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 Kb6Mw<&;$U@=_>dD diff --git a/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-xxhdpi/adaptiveproduct_youtube_foreground_color_108.png deleted file mode 100644 index 777daea51e45da543dba2fa1e951dfe34fdc6d0d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7429 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 diff --git a/src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png b/src/main/resources/branding/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 6e2178566d4ff9f8c2f9512b6bb85d9bcac3ab27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6719 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 E0JlHujQ{`u diff --git a/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png b/src/main/resources/branding/mipmap-xxxhdpi/adaptiveproduct_youtube_foreground_color_108.png deleted file mode 100644 index 0abe542a1ad774189569a9098e32b1a24ca9da64..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7945 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 T48Ir{7#KWV{an^LB{Ts5N~lsp diff --git a/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png b/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index c0505bf87c101680afb0ebf7abba0fb0a38a7da6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8086 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 diff --git a/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png b/src/main/resources/branding/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index c0505bf87c101680afb0ebf7abba0fb0a38a7da6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8086 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 diff --git a/src/main/resources/downloads/drawable/revanced_yt_download_button.xml b/src/main/resources/downloads/drawable/revanced_yt_download_button.xml deleted file mode 100644 index 69ab699..0000000 --- a/src/main/resources/downloads/drawable/revanced_yt_download_button.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml b/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml deleted file mode 100644 index 2325478..0000000 --- a/src/main/resources/downloads/host/layout/youtube_controls_bottom_ui_container.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/main/resources/downloads/host/values/strings.xml b/src/main/resources/downloads/host/values/strings.xml deleted file mode 100644 index 957d490..0000000 --- a/src/main/resources/downloads/host/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - is not installed. Please install it. - diff --git a/src/main/resources/microg/host/values/strings.xml b/src/main/resources/microg/host/values/strings.xml deleted file mode 100644 index c5c1f69..0000000 --- a/src/main/resources/microg/host/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Vanced MicroG is not installed. Please install it. - diff --git a/src/main/resources/returnyoutubedislike/host/values/strings.xml b/src/main/resources/returnyoutubedislike/host/values/strings.xml deleted file mode 100644 index a223873..0000000 --- a/src/main/resources/returnyoutubedislike/host/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Enable Return YouTube Dislike - Switch this on to see the dislike counts again - Return YouTube Dislike patch - This patch uses the Return YouTube Dislike API from https://returnyoutubedislike.com. Tap to learn more - \ No newline at end of file diff --git a/src/main/resources/settings/drawable-ldrtl-xxxhdpi/quantum_ic_arrow_back_white_24.png b/src/main/resources/settings/drawable-ldrtl-xxxhdpi/quantum_ic_arrow_back_white_24.png deleted file mode 100644 index d409b544b7f62950a69d7d1ea58e97ef6c5ea546..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CW^n1EEhEy=Vy>(IWAcF); zB5OvFdVM~Z^#jRC2hP?+A6%!>S+M&&0|?CY+5WHf<+c3=cYld5i{7uR*dFu3_k^80 zr;v)r1O>+?78s+Y^hvl+^?@)>&q}9DvlI?!n&d5>cl684%gg=e+tvPpF#gH@a;rDp m?0q==@?-VK`JbynR#-6BO<9^PT)eUc#Pf9Zb6Mw<&;$V5988D+ diff --git a/src/main/resources/settings/drawable-xxxhdpi/quantum_ic_arrow_back_white_24.png b/src/main/resources/settings/drawable-xxxhdpi/quantum_ic_arrow_back_white_24.png deleted file mode 100644 index e27034d67874687a900f0f960c662e94cd633e2a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CWbb7ithEy=Vy~Qcm>>%J0 z$dXVrx5vDuu!r^Cx+?#J?_*k0)aNlWFyw3vEvsAo=1*B+ diff --git a/src/main/resources/settings/layout/revanced_settings_toolbar.xml b/src/main/resources/settings/layout/revanced_settings_toolbar.xml deleted file mode 100644 index 86c7177..0000000 --- a/src/main/resources/settings/layout/revanced_settings_toolbar.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml b/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml deleted file mode 100644 index 21ff597..0000000 --- a/src/main/resources/settings/layout/revanced_settings_with_toolbar.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml b/src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml deleted file mode 100644 index 31b20d9..0000000 --- a/src/main/resources/settings/layout/revanced_settings_with_toolbar_layout.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/main/resources/settings/xml/revanced_prefs.xml b/src/main/resources/settings/xml/revanced_prefs.xml deleted file mode 100644 index 9562c00..0000000 --- a/src/main/resources/settings/xml/revanced_prefs.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - \ No newline at end of file diff --git a/src/main/resources/sponsorblock/drawable-xxxhdpi/quantum_ic_skip_next_white_24.png b/src/main/resources/sponsorblock/drawable-xxxhdpi/quantum_ic_skip_next_white_24.png deleted file mode 100644 index 19c4929cca13b462dee093c2156ca904e52c4fad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 357 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CW>Ug?1hEy=Vy=AD!n#kb# zu+wGXCC#l@zL+JjhaKR$!6+?Zy`gDi!$yX$*_x%ZGSw!o-qYFD`Ap^cAMOeI5BL5) zFL4G2>VoGL&3Gt({(Rg1xw`frY{hdNK22?ZGnvuz)2v`Kg~%dj)-BIvHZq=c*IU`} zZ3eTM!p*01cs;J&N$uy%(6>xuo^(FOk#TJ{C)bOpCZ=7}HZ-hL)mf0u$@3!W5Yw({ z2T-{nS%U`t87KEUW#^r&KeBtyM0+>)PvVj_UOrC@w?COxyUPe>XM%@5(&1@5$>+j7+;qCN${Dsx0ts=W_VFoA&{SfC57u r3x@!MJrfIufPzB<10&Oc=h8Oks&u}*+`+@Zz`)??>gTe~DWM4fK021Z diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_adjust.xml b/src/main/resources/sponsorblock/drawable/ic_sb_adjust.xml deleted file mode 100644 index 76a4b8b..0000000 --- a/src/main/resources/sponsorblock/drawable/ic_sb_adjust.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_compare.xml b/src/main/resources/sponsorblock/drawable/ic_sb_compare.xml deleted file mode 100644 index 04cc65e..0000000 --- a/src/main/resources/sponsorblock/drawable/ic_sb_compare.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_edit.xml b/src/main/resources/sponsorblock/drawable/ic_sb_edit.xml deleted file mode 100644 index e93574b..0000000 --- a/src/main/resources/sponsorblock/drawable/ic_sb_edit.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_logo.xml b/src/main/resources/sponsorblock/drawable/ic_sb_logo.xml deleted file mode 100644 index c39b9e0..0000000 --- a/src/main/resources/sponsorblock/drawable/ic_sb_logo.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_publish.xml b/src/main/resources/sponsorblock/drawable/ic_sb_publish.xml deleted file mode 100644 index de4e58d..0000000 --- a/src/main/resources/sponsorblock/drawable/ic_sb_publish.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml b/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml deleted file mode 100644 index 97db9c9..0000000 --- a/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml b/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml deleted file mode 100644 index 9779626..0000000 --- a/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/main/resources/sponsorblock/host/values/strings.xml b/src/main/resources/sponsorblock/host/values/strings.xml deleted file mode 100644 index 2f48383..0000000 --- a/src/main/resources/sponsorblock/host/values/strings.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - Enable SponsorBlock - SponsorBlock is a crowd-sourced system for skipping annoying parts in YouTube videos - Enable new segment adding - Switch this on to enable experimental segment adding (has button visibility issues) - What to do with different segments - General - Show a toast when skipping segment automatically - Click to see an example toast - Skip count tracking - This lets SponsorBlock leaderboard system know how much time people have saved. The extension sends a message to the server each time you skip a segment - Adjusting new segment step - This is the number of milliseconds you can move when you use the time adjustment buttons while adding new segment - Minimum segment duration - Segments shorter than the set value (in seconds) will not be skipped or shown in the player - Your private user id - This should be kept private. This is like a password and should not be shared with anyone. If someone has this, they can impersonate you - Import/Export settings - This is your entire configuration that is applicable in the desktop extension in JSON. This includes your Private userID, so be sure to share this wisely. - Change API URL - The address SponsorBlock uses to make calls to the server. <b>Don\'t change this unless you know what you\'re doing.</b> - Settings were successfully imported - Failed to import settings - Failed to export settings - Cache segments locally - Frequently watched videos (eg. music videos) may store segments in app cache to make skipping segments faster - Clear SponsorBlock segments cache - Sponsor - Paid promotion, paid referrals and direct advertisements - Intermission/Intro Animation - An interval without actual content. Could be a pause, static frame, repeating animation - Endcards/Credits - Credits or when the YouTube endcards appear. Not for spoken conclusions - Interaction Reminder (Subscribe) - When there is a short reminder to like, subscribe, follow or interact with them on any free or paid platform - Unpaid/Self Promotion - When there is unpaid or self promotion. This includes specific sections about merchandise, donations, or information about who they collaborated with - Music: Non-Music Section - Only for use in music videos. Skips parts of the video not in official mixes - Filler Tangent/Jokes - Tangential scenes added only for filler or humor that are not required to understand the main content of the video. This should not include context or background details - Skipped a sponsor segment - Skipped sponsor - Skipped intro - Skipped outro - Skipped annoying reminder - Skipped self promotion - Skipped a non-music section - Skipped preview - Skipped filler - Skipped unsubmitted segment - Skip automatically - Skip automatically once - Show a skip button - Don\'t do anything - Skip segment - About - This app uses the API from SponsorBlock - Tap to learn more, and see downloads for other platforms at: sponsor.ajay.app - Integration made by JakubWeg, recoded by oSumAtrIX - Tap to skip - - Can\'t submit the segment: %s - Unable to submit segments: Status: %d %s - Can\'t submit the segment.\nRate Limited (Too many from the same user or IP) - Can\'t submit the segment.\n\n%s - Can\'t submit the segment.\nAlready exists - Segment submitted successfully - Submitting segment… - - Unable to vote for segment: Status: %d %s - Can\'t vote for segment.\nRate Limited (Too many from the same user or IP) - Can\'t vote for segment.\n\n%s - Voted successfully - Voting for segment… - Upvote - Downvote - Change category - There are no segments to vote for - Enable voting - Switch this on to enable voting. - - Choose the segment category - You\'ve disabled this category in the settings, enable it to be able to submit - New SponsorBlock segment - Set %02d:%02d:%04d as the start or end of a new segment? - start - end - now - Time the segment begins at - Time the segment ends at - Beginning of segment set - End of segment set - Are the times correct? - The segment lasts from %02d:%02d to %02d:%02d (%d minutes %02d seconds)\nIs it ready to submit? - Mark two locations on the time bar first - Edit timing of segment manually - Do you want to edit the timing for the start or end of the segment? - Done - Invalid time given - - View guidelines - Guidelines contain tips and rules about submitting segments - There are guidelines - It\'s recommended to read the SponsorBlock guidelines before submitting any segment - Already read - Show me - - Show time without segments - This time appears in brackets next to the current time. This shows the total video duration minus any segments. - Preview/Recap - Recap of previous episodes, or a preview of what\'s coming up later in the current video or future videos in the same series. Clips should not provide additional information. - Stats - Loading.. - SponsorBlock is disabled - Your username: <b>%s</b> - Click to change your username - Unable to change username: Status: %d %s - Username successfully changed - Submissions: <b>%s</b> - You\'ve saved people from <b>%s</b> segments. - That\'s <b>%s</b> of their lives. Click to see the leaderboard - You\'ve skipped <b>%s</b> segments. - That\'s <b>%s</b>. - minutes - Are you looking for changing colors? - You can now change a category\'s color by clicking on it above. - Choose the category - Color changed - Color reset - Invalid hex code - Change - Reset - - Segments - SB Browser - - API URL changed - API URL reset - Provided API URL is invalid - diff --git a/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml b/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml deleted file mode 100644 index 6bc670f..0000000 --- a/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/main/resources/sponsorblock/layout/new_segment.xml b/src/main/resources/sponsorblock/layout/new_segment.xml deleted file mode 100644 index 155907c..0000000 --- a/src/main/resources/sponsorblock/layout/new_segment.xml +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml b/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml deleted file mode 100644 index 3ceb8c3..0000000 --- a/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/main/resources/swipecontrols/drawable/ic_sc_brightness_auto.xml b/src/main/resources/swipecontrols/drawable/ic_sc_brightness_auto.xml deleted file mode 100644 index 469b335..0000000 --- a/src/main/resources/swipecontrols/drawable/ic_sc_brightness_auto.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/src/main/resources/swipecontrols/drawable/ic_sc_brightness_manual.xml b/src/main/resources/swipecontrols/drawable/ic_sc_brightness_manual.xml deleted file mode 100644 index 2f6c707..0000000 --- a/src/main/resources/swipecontrols/drawable/ic_sc_brightness_manual.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/src/main/resources/swipecontrols/drawable/ic_sc_volume_mute.xml b/src/main/resources/swipecontrols/drawable/ic_sc_volume_mute.xml deleted file mode 100644 index 73dc595..0000000 --- a/src/main/resources/swipecontrols/drawable/ic_sc_volume_mute.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/src/main/resources/swipecontrols/drawable/ic_sc_volume_normal.xml b/src/main/resources/swipecontrols/drawable/ic_sc_volume_normal.xml deleted file mode 100644 index 30dff4b..0000000 --- a/src/main/resources/swipecontrols/drawable/ic_sc_volume_normal.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/src/main/resources/theme/values-night-v31/styles.xml b/src/main/resources/theme/values-night-v31/styles.xml deleted file mode 100644 index 53da895..0000000 --- a/src/main/resources/theme/values-night-v31/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - -