From d86851baf1ef1993f5ba9543a4a3fe8d50c3a199 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 7 Sep 2023 10:41:06 +0400 Subject: [PATCH 01/69] fix(YouTube - Hide layout components): Always hide redundant 'player audio track' button (#473) --- .../patches/components/LayoutComponentsFilter.java | 10 +++++++++- .../revanced/integrations/settings/SettingsEnum.java | 1 - 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 67811a8991..8e88200a2e 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -92,8 +92,16 @@ public LayoutComponentsFilter() { "channel_guidelines_entry_banner" ); + // The player audio track button does the exact same function as the audio track flyout menu option. + // But if the copy url button is shown, these button clashes and the the audio button does not work. + // Previously this was a setting to show/hide the player button. + // But it was decided it's simpler to always hide this button because: + // - it doesn't work with copy video url feature + // - the button is rare + // - always hiding makes the ReVanced settings simpler and easier to understand + // - nobody is going to notice the redundant button is always hidden final var audioTrackButton = new StringFilterGroup( - SettingsEnum.HIDE_AUDIO_TRACK_BUTTON, + null, "multi_feed_icon_button" ); diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index c7e6c432f4..68ebab03b7 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -97,7 +97,6 @@ public enum SettingsEnum { DISABLE_RESUMING_SHORTS_PLAYER("revanced_disable_resuming_shorts_player", BOOLEAN, FALSE), HIDE_ALBUM_CARDS("revanced_hide_album_cards", BOOLEAN, FALSE, true), HIDE_ARTIST_CARDS("revanced_hide_artist_cards", BOOLEAN, FALSE), - HIDE_AUDIO_TRACK_BUTTON("revanced_hide_audio_track_button", BOOLEAN, FALSE), HIDE_AUTOPLAY_BUTTON("revanced_hide_autoplay_button", BOOLEAN, TRUE, true), HIDE_BREAKING_NEWS("revanced_hide_breaking_news", BOOLEAN, TRUE, true), HIDE_CAPTIONS_BUTTON("revanced_hide_captions_button", BOOLEAN, FALSE), From 830cfb561f43e9954aa0e2d6b236abbd7217079f Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 7 Sep 2023 06:44:50 +0000 Subject: [PATCH 02/69] chore(release): 0.117.2-dev.1 [skip ci] ## [0.117.2-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.1...v0.117.2-dev.1) (2023-09-07) ### Bug Fixes * **YouTube - Hide layout components:** Always hide redundant 'player audio track' button ([#473](https://github.com/ReVanced/revanced-integrations/issues/473)) ([d86851b](https://github.com/ReVanced/revanced-integrations/commit/d86851baf1ef1993f5ba9543a4a3fe8d50c3a199)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a28a03e043..efeba4f3bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.117.2-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.1...v0.117.2-dev.1) (2023-09-07) + + +### Bug Fixes + +* **YouTube - Hide layout components:** Always hide redundant 'player audio track' button ([#473](https://github.com/ReVanced/revanced-integrations/issues/473)) ([d86851b](https://github.com/ReVanced/revanced-integrations/commit/d86851baf1ef1993f5ba9543a4a3fe8d50c3a199)) + ## [0.117.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.0...v0.117.1) (2023-09-03) diff --git a/gradle.properties b/gradle.properties index f547f97e49..3ebe55a6d4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.117.1 +version = 0.117.2-dev.1 From 17ed39673954a5b571bc1654be20afc235682ca4 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Fri, 8 Sep 2023 00:10:38 +0400 Subject: [PATCH 03/69] fix(YouTube - Custom filter): Use new lines between components instead of commas (#475) --- .../patches/components/LithoFilterPatch.java | 2 +- .../integrations/settings/SettingsEnum.java | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index 90aa678105..44cbbeaf10 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -88,7 +88,7 @@ public FilterGroupResult check(final String string) { final class CustomFilterGroup extends StringFilterGroup { public CustomFilterGroup(final SettingsEnum setting, final SettingsEnum filter) { - super(setting, filter.getString().split(",")); + super(setting, filter.getString().split("\\s+")); } } diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 68ebab03b7..7b578a630e 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -36,8 +36,6 @@ public enum SettingsEnum { // Video HDR_AUTO_BRIGHTNESS("revanced_hdr_auto_brightness", BOOLEAN, TRUE), SHOW_OLD_VIDEO_QUALITY_MENU("revanced_show_old_video_quality_menu", BOOLEAN, TRUE), - @Deprecated - DEPRECATED_SHOW_OLD_VIDEO_QUALITY_MENU("revanced_show_old_video_menu", BOOLEAN, TRUE), REMEMBER_VIDEO_QUALITY_LAST_SELECTED("revanced_remember_video_quality_last_selected", BOOLEAN, TRUE), VIDEO_QUALITY_DEFAULT_WIFI("revanced_video_quality_default_wifi", INTEGER, -2), VIDEO_QUALITY_DEFAULT_MOBILE("revanced_video_quality_default_mobile", INTEGER, -2), @@ -367,13 +365,20 @@ private static void loadAllSettings() { // region Migration - // TODO: do _not_ delete this SB private user id migration property until sometime in 2024. + // Do _not_ delete this SB private user id migration property until sometime in 2024. // This is the only setting that cannot be reconfigured if lost, // and more time should be given for users who rarely upgrade. migrateOldSettingToNew(DEPRECATED_SB_UUID_OLD_MIGRATION_SETTING, SB_PRIVATE_USER_ID); - // TODO: delete DEPRECATED_SHOW_OLD_VIDEO_QUALITY_MENU (When? anytime). - migrateOldSettingToNew(DEPRECATED_SHOW_OLD_VIDEO_QUALITY_MENU, SHOW_OLD_VIDEO_QUALITY_MENU); + // This migration may need to remain here for a while. + // Older online guides will still reference using commas, + // and this code will automatically convert anything the user enters to newline format, + // and also migrate any imported older settings that using commas. + String componentsToFilter = SettingsEnum.CUSTOM_FILTER_STRINGS.getString(); + if (componentsToFilter.contains(",")) { + LogHelper.printInfo(() -> "Migrating custom filter strings to new line format"); + SettingsEnum.CUSTOM_FILTER_STRINGS.saveValue(componentsToFilter.replace(",", "\n")); + } // endregion } From acf7e2d1ddbc0143a609c4aadbc4db81eeb1a32a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 7 Sep 2023 20:15:50 +0000 Subject: [PATCH 04/69] chore(release): 0.117.2-dev.2 [skip ci] ## [0.117.2-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.1...v0.117.2-dev.2) (2023-09-07) ### Bug Fixes * **YouTube - Custom filter:** Use new lines between components instead of commas ([#475](https://github.com/ReVanced/revanced-integrations/issues/475)) ([17ed396](https://github.com/ReVanced/revanced-integrations/commit/17ed39673954a5b571bc1654be20afc235682ca4)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efeba4f3bf..2353dde403 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.117.2-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.1...v0.117.2-dev.2) (2023-09-07) + + +### Bug Fixes + +* **YouTube - Custom filter:** Use new lines between components instead of commas ([#475](https://github.com/ReVanced/revanced-integrations/issues/475)) ([17ed396](https://github.com/ReVanced/revanced-integrations/commit/17ed39673954a5b571bc1654be20afc235682ca4)) + ## [0.117.2-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.1...v0.117.2-dev.1) (2023-09-07) diff --git a/gradle.properties b/gradle.properties index 3ebe55a6d4..777cf9438d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.117.2-dev.1 +version = 0.117.2-dev.2 From e3b8e8be41796d0300c8421e28e5b8cf43ffb25e Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sat, 9 Sep 2023 12:52:47 +0400 Subject: [PATCH 05/69] fix(YouTube - ReturnYouTubeDislike): Add debug logging to litho text (#476) --- .../integrations/patches/ReturnYouTubeDislikePatch.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index a3d2fc3314..48a7e81aab 100644 --- a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -154,6 +154,8 @@ public static CharSequence onLithoTextLoaded(@NonNull Object conversionContext, } String conversionContextString = conversionContext.toString(); + LogHelper.printDebug(() -> "conversionContext: " + conversionContextString); + final boolean isSegmentedButton; if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) { isSegmentedButton = true; From f0bfcef0d7a454e5c099f6ce92f5ec8348a228f5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 9 Sep 2023 08:56:11 +0000 Subject: [PATCH 06/69] chore(release): 0.117.2-dev.3 [skip ci] ## [0.117.2-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.2...v0.117.2-dev.3) (2023-09-09) ### Bug Fixes * **YouTube - ReturnYouTubeDislike:** Add debug logging to litho text ([#476](https://github.com/ReVanced/revanced-integrations/issues/476)) ([e3b8e8b](https://github.com/ReVanced/revanced-integrations/commit/e3b8e8be41796d0300c8421e28e5b8cf43ffb25e)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2353dde403..b652b7767f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [0.117.2-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.2...v0.117.2-dev.3) (2023-09-09) + + +### Bug Fixes + +* **YouTube - ReturnYouTubeDislike:** Add debug logging to litho text ([#476](https://github.com/ReVanced/revanced-integrations/issues/476)) ([e3b8e8b](https://github.com/ReVanced/revanced-integrations/commit/e3b8e8be41796d0300c8421e28e5b8cf43ffb25e)) + ## [0.117.2-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.1...v0.117.2-dev.2) (2023-09-07) diff --git a/gradle.properties b/gradle.properties index 777cf9438d..bcbb061d22 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.117.2-dev.2 +version = 0.117.2-dev.3 From 526d66f6a91e0ed907db609a4adaa97f3239898b Mon Sep 17 00:00:00 2001 From: Traktores <144092020+Traktores@users.noreply.github.com> Date: Thu, 14 Sep 2023 01:11:49 +0000 Subject: [PATCH 07/69] feat(TU Dortmund): Add `Show on lockscreen` patch (#472) Co-authored-by: oSumAtrIX --- .../lockscreen/ShowOnLockscreenPatch.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 app/src/main/java/app/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch.java diff --git a/app/src/main/java/app/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch.java b/app/src/main/java/app/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch.java new file mode 100644 index 0000000000..2260de24d7 --- /dev/null +++ b/app/src/main/java/app/revanced/tudortmund/lockscreen/ShowOnLockscreenPatch.java @@ -0,0 +1,46 @@ +package app.revanced.tudortmund.lockscreen; + +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.Build; +import android.view.Display; +import android.view.Window; +import androidx.appcompat.app.AppCompatActivity; + +import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; +import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; + +public class ShowOnLockscreenPatch { + /** + * @noinspection deprecation + */ + public static Window getWindow(AppCompatActivity activity, float brightness) { + Window window = activity.getWindow(); + + if (brightness >= 0) { + // High brightness set, therefore show on lockscreen. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) activity.setShowWhenLocked(true); + else window.addFlags(FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD); + } else { + // Ignore brightness reset when the screen is turned off. + DisplayManager displayManager = (DisplayManager) activity.getSystemService(Context.DISPLAY_SERVICE); + + boolean isScreenOn = false; + for (Display display : displayManager.getDisplays()) { + if (display.getState() == Display.STATE_OFF) continue; + + isScreenOn = true; + break; + } + + if (isScreenOn) { + // Hide on lockscreen. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) activity.setShowWhenLocked(false); + else window.clearFlags(FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD); + } + } + + return window; + } + +} From 7b524efdbdf51438c0b69f4271663bd4c9018311 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 14 Sep 2023 01:15:52 +0000 Subject: [PATCH 08/69] chore(release): 0.118.0-dev.1 [skip ci] # [0.118.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.3...v0.118.0-dev.1) (2023-09-14) ### Features * **TU Dortmund:** Add `Show on lockscreen` patch ([#472](https://github.com/ReVanced/revanced-integrations/issues/472)) ([526d66f](https://github.com/ReVanced/revanced-integrations/commit/526d66f6a91e0ed907db609a4adaa97f3239898b)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b652b7767f..a399e98f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.3...v0.118.0-dev.1) (2023-09-14) + + +### Features + +* **TU Dortmund:** Add `Show on lockscreen` patch ([#472](https://github.com/ReVanced/revanced-integrations/issues/472)) ([526d66f](https://github.com/ReVanced/revanced-integrations/commit/526d66f6a91e0ed907db609a4adaa97f3239898b)) + ## [0.117.2-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.2...v0.117.2-dev.3) (2023-09-09) diff --git a/gradle.properties b/gradle.properties index bcbb061d22..3c53adebfa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.117.2-dev.3 +version = 0.118.0-dev.1 From 4a242c7a9191411414c10e8637af72c2b9bec5e9 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 14 Sep 2023 16:57:22 +0200 Subject: [PATCH 09/69] refactor: Use try block for auto closeable --- .../twitch/adblock/PurpleAdblockService.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/app/revanced/twitch/adblock/PurpleAdblockService.java b/app/src/main/java/app/revanced/twitch/adblock/PurpleAdblockService.java index 5b2db973b2..07e47dca30 100644 --- a/app/src/main/java/app/revanced/twitch/adblock/PurpleAdblockService.java +++ b/app/src/main/java/app/revanced/twitch/adblock/PurpleAdblockService.java @@ -1,14 +1,13 @@ package app.revanced.twitch.adblock; -import java.util.HashMap; -import java.util.Map; - import app.revanced.twitch.api.RetrofitClient; import app.revanced.twitch.utils.LogHelper; import app.revanced.twitch.utils.ReVancedUtils; import okhttp3.HttpUrl; import okhttp3.Request; -import okhttp3.ResponseBody; + +import java.util.HashMap; +import java.util.Map; public class PurpleAdblockService implements IAdblockService { private final Map tunnels = new HashMap<>() {{ @@ -36,9 +35,13 @@ public Boolean isAvailable() { if (!response.isSuccessful()) { LogHelper.error("PurpleAdBlock tunnel $tunnel returned an error: HTTP code %d", response.code()); LogHelper.debug(response.message()); - if (response.errorBody() != null) { - LogHelper.debug(((ResponseBody) response.errorBody()).string()); + + try (var errorBody = response.errorBody()) { + if (errorBody != null) { + LogHelper.debug(errorBody.string()); + } } + success = false; } } catch (Exception ex) { From 2c3418041cf19ae4c1c7b67eda8398578384b753 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 14 Sep 2023 21:27:33 +0200 Subject: [PATCH 10/69] feat(Twitch - Block embedded ads): Switch from `ttv.lol` to `luminous.dev` --- .../twitch/adblock/LuminousService.java | 46 ++++++++++++ .../twitch/adblock/TTVLolService.java | 70 ------------------- .../twitch/api/RequestInterceptor.java | 17 +++-- .../twitch/settings/SettingsEnum.java | 14 ++-- 4 files changed, 60 insertions(+), 87 deletions(-) create mode 100644 app/src/main/java/app/revanced/twitch/adblock/LuminousService.java delete mode 100644 app/src/main/java/app/revanced/twitch/adblock/TTVLolService.java diff --git a/app/src/main/java/app/revanced/twitch/adblock/LuminousService.java b/app/src/main/java/app/revanced/twitch/adblock/LuminousService.java new file mode 100644 index 0000000000..34acece3f9 --- /dev/null +++ b/app/src/main/java/app/revanced/twitch/adblock/LuminousService.java @@ -0,0 +1,46 @@ +package app.revanced.twitch.adblock; + +import app.revanced.twitch.utils.LogHelper; +import app.revanced.twitch.utils.ReVancedUtils; +import okhttp3.HttpUrl; +import okhttp3.Request; + +public class LuminousService implements IAdblockService { + @Override + public String friendlyName() { + return ReVancedUtils.getString("revanced_proxy_luminous"); + } + + @Override + public Integer maxAttempts() { + return 2; + } + + @Override + public Boolean isAvailable() { + return true; + } + + @Override + public Request rewriteHlsRequest(Request originalRequest) { + var type = IAdblockService.isVod(originalRequest) ? "vod" : "playlist"; + var url = HttpUrl.parse("https://eu.luminous.dev/" + + type + + "/" + + IAdblockService.channelName(originalRequest) + + ".m3u8" + + "%3Fallow_source%3Dtrue%26allow_audio_only%3Dtrue%26fast_bread%3Dtrue" + ); + + if (url == null) { + LogHelper.error("Failed to parse rewritten URL"); + return null; + } + + // Overwrite old request + return new Request.Builder() + .get() + .url(url) + .build(); + } +} diff --git a/app/src/main/java/app/revanced/twitch/adblock/TTVLolService.java b/app/src/main/java/app/revanced/twitch/adblock/TTVLolService.java deleted file mode 100644 index 6aa31d823f..0000000000 --- a/app/src/main/java/app/revanced/twitch/adblock/TTVLolService.java +++ /dev/null @@ -1,70 +0,0 @@ -package app.revanced.twitch.adblock; - -import java.util.ArrayList; -import java.util.Random; - -import app.revanced.twitch.utils.LogHelper; -import app.revanced.twitch.utils.ReVancedUtils; -import okhttp3.HttpUrl; -import okhttp3.Request; - -public class TTVLolService implements IAdblockService { - @Override - public String friendlyName() { - return ReVancedUtils.getString("revanced_proxy_ttv_lol"); - } - - // TTV.lol is sometimes unstable - @Override - public Integer maxAttempts() { - return 4; - } - - @Override - public Boolean isAvailable() { - return true; - } - - @Override - public Request rewriteHlsRequest(Request originalRequest) { - - var type = "vod"; - if (!IAdblockService.isVod(originalRequest)) - type = "playlist"; - - var url = HttpUrl.parse("https://api.ttv.lol/" + - type + "/" + - IAdblockService.channelName(originalRequest) + - ".m3u8" + nextQuery() - ); - - if (url == null) { - LogHelper.error("Failed to parse rewritten URL"); - return null; - } - - // Overwrite old request - return new Request.Builder() - .get() - .url(url) - .addHeader("X-Donate-To", "https://ttv.lol/donate") - .build(); - } - - private String nextQuery() { - return SAMPLE_QUERY.replace("", generateSessionId()); - } - - private String generateSessionId() { - final var chars = "abcdef0123456789".toCharArray(); - - var sessionId = new ArrayList(); - for (int i = 0; i < 32; i++) - sessionId.add(chars[randomSource.nextInt(16)]); - - return sessionId.toString(); - } - - private final Random randomSource = new Random(); - private final String SAMPLE_QUERY = "%3Fallow_source%3Dtrue%26fast_bread%3Dtrue%26allow_audio_only%3Dtrue%26p%3D0%26play_session_id%3D%26player_backend%3Dmediaplayer%26warp%3Dfalse%26force_preroll%3Dfalse%26mobile_cellular%3Dfalse"; -} diff --git a/app/src/main/java/app/revanced/twitch/api/RequestInterceptor.java b/app/src/main/java/app/revanced/twitch/api/RequestInterceptor.java index 34cda6f6ac..f571c23954 100644 --- a/app/src/main/java/app/revanced/twitch/api/RequestInterceptor.java +++ b/app/src/main/java/app/revanced/twitch/api/RequestInterceptor.java @@ -1,21 +1,20 @@ package app.revanced.twitch.api; -import static app.revanced.twitch.adblock.IAdblockService.channelName; -import static app.revanced.twitch.adblock.IAdblockService.isVod; - import androidx.annotation.NonNull; - -import java.io.IOException; - import app.revanced.twitch.adblock.IAdblockService; +import app.revanced.twitch.adblock.LuminousService; import app.revanced.twitch.adblock.PurpleAdblockService; -import app.revanced.twitch.adblock.TTVLolService; import app.revanced.twitch.settings.SettingsEnum; import app.revanced.twitch.utils.LogHelper; import app.revanced.twitch.utils.ReVancedUtils; import okhttp3.Interceptor; import okhttp3.Response; +import java.io.IOException; + +import static app.revanced.twitch.adblock.IAdblockService.channelName; +import static app.revanced.twitch.adblock.IAdblockService.isVod; + public class RequestInterceptor implements Interceptor { private IAdblockService activeService = null; @@ -87,8 +86,8 @@ public Response intercept(@NonNull Chain chain) throws IOException { private void updateActiveService() { var current = SettingsEnum.BLOCK_EMBEDDED_ADS.getString(); - if (current.equals(ReVancedUtils.getString("key_revanced_proxy_ttv_lol")) && !(activeService instanceof TTVLolService)) - activeService = new TTVLolService(); + if (current.equals(ReVancedUtils.getString("key_revanced_proxy_luminous")) && !(activeService instanceof LuminousService)) + activeService = new LuminousService(); else if (current.equals(ReVancedUtils.getString("key_revanced_proxy_purpleadblock")) && !(activeService instanceof PurpleAdblockService)) activeService = new PurpleAdblockService(); else if (current.equals(ReVancedUtils.getString("key_revanced_proxy_disabled"))) diff --git a/app/src/main/java/app/revanced/twitch/settings/SettingsEnum.java b/app/src/main/java/app/revanced/twitch/settings/SettingsEnum.java index 6e1833873e..6a2f187e84 100644 --- a/app/src/main/java/app/revanced/twitch/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/twitch/settings/SettingsEnum.java @@ -1,23 +1,21 @@ package app.revanced.twitch.settings; -import static java.lang.Boolean.FALSE; -import static java.lang.Boolean.TRUE; -import static app.revanced.twitch.settings.SettingsEnum.ReturnType.BOOLEAN; -import static app.revanced.twitch.settings.SettingsEnum.ReturnType.STRING; - import android.content.Context; import android.content.SharedPreferences; - import androidx.annotation.NonNull; - import app.revanced.twitch.utils.LogHelper; import app.revanced.twitch.utils.ReVancedUtils; +import static app.revanced.twitch.settings.SettingsEnum.ReturnType.BOOLEAN; +import static app.revanced.twitch.settings.SettingsEnum.ReturnType.STRING; +import static java.lang.Boolean.FALSE; +import static java.lang.Boolean.TRUE; + public enum SettingsEnum { /* Ads */ BLOCK_VIDEO_ADS("revanced_block_video_ads", BOOLEAN, TRUE), BLOCK_AUDIO_ADS("revanced_block_audio_ads", BOOLEAN, TRUE), - BLOCK_EMBEDDED_ADS("revanced_block_embedded_ads", STRING, "ttv-lol"), + BLOCK_EMBEDDED_ADS("revanced_block_embedded_ads", STRING, "luminous"), /* Chat */ SHOW_DELETED_MESSAGES("revanced_show_deleted_messages", STRING, "cross-out"), From aa10de41b6903f78541fa0b17cb22741ab5b5815 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 14 Sep 2023 21:26:51 +0000 Subject: [PATCH 11/69] chore(release): 0.118.0-dev.2 [skip ci] # [0.118.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.1...v0.118.0-dev.2) (2023-09-14) ### Features * **Twitch - Block embedded ads:** Switch from `ttv.lol` to `luminous.dev` ([2c34180](https://github.com/ReVanced/revanced-integrations/commit/2c3418041cf19ae4c1c7b67eda8398578384b753)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a399e98f29..85091da317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.1...v0.118.0-dev.2) (2023-09-14) + + +### Features + +* **Twitch - Block embedded ads:** Switch from `ttv.lol` to `luminous.dev` ([2c34180](https://github.com/ReVanced/revanced-integrations/commit/2c3418041cf19ae4c1c7b67eda8398578384b753)) + # [0.118.0-dev.1](https://github.com/ReVanced/revanced-integrations/compare/v0.117.2-dev.3...v0.118.0-dev.1) (2023-09-14) diff --git a/gradle.properties b/gradle.properties index 3c53adebfa..38ad933196 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.1 +version = 0.118.0-dev.2 From 2352fa542658035c5f4400fb5892217887710e4d Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 19 Sep 2023 06:22:15 +0400 Subject: [PATCH 12/69] fix(YouTube): fix old quality and custom speed not working on tablets (#477) --- .../quality/OldVideoQualityMenuPatch.java | 73 ++++++------------- .../speed/CustomPlaybackSpeedPatch.java | 68 ++++++++--------- .../com/facebook/litho/ComponentHost.java | 10 --- 3 files changed, 57 insertions(+), 94 deletions(-) delete mode 100644 dummy/src/main/java/com/facebook/litho/ComponentHost.java diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java index 70defb4c36..0d914ab3d7 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/quality/OldVideoQualityMenuPatch.java @@ -3,71 +3,44 @@ import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.widget.LinearLayout; import android.widget.ListView; -import androidx.annotation.NonNull; - import app.revanced.integrations.patches.components.VideoQualityMenuFilterPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; -import com.facebook.litho.ComponentHost; -import kotlin.Deprecated; -// This patch contains the logic to show the old video quality menu. -// Two methods are required, because the quality menu is a RecyclerView in the new YouTube version -// and a ListView in the old one. +/** + * This patch contains the logic to show the old video quality menu. + * Two methods are required, because the quality menu is a RecyclerView in the new YouTube version + * and a ListView in the old one. + */ public final class OldVideoQualityMenuPatch { - public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { + /** + * Injection point. + */ + public static void onFlyoutMenuCreate(RecyclerView recyclerView) { if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; - // The quality menu is a RecyclerView with 3 children. The third child is the "Advanced" quality menu. - addRecyclerListener(linearLayout, 3, 2, recyclerView -> { - // Check if the current view is the quality menu. - if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) { - VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false; - linearLayout.setVisibility(View.GONE); + recyclerView.getViewTreeObserver().addOnDrawListener(() -> { + try { + // Check if the current view is the quality menu. + if (VideoQualityMenuFilterPatch.isVideoQualityMenuVisible) { + VideoQualityMenuFilterPatch.isVideoQualityMenuVisible = false; + ((ViewGroup) recyclerView.getParent().getParent().getParent()).setVisibility(View.GONE); - // Click the "Advanced" quality menu to show the "old" quality menu. - ((ComponentHost) recyclerView.getChildAt(0)).getChildAt(3).performClick(); - LogHelper.printDebug(() -> "Advanced quality menu in new type of quality menu clicked"); + // Click the "Advanced" quality menu to show the "old" quality menu. + ((ViewGroup) recyclerView.getChildAt(0)).getChildAt(3).performClick(); + } + } catch (Exception ex) { + LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex); } }); } - public static void addRecyclerListener(@NonNull LinearLayout linearLayout, - int expectedLayoutChildCount, int recyclerViewIndex, - @NonNull RecyclerViewGlobalLayoutListener listener) { - if (linearLayout.getChildCount() != expectedLayoutChildCount) return; - - var layoutChild = linearLayout.getChildAt(recyclerViewIndex); - if (!(layoutChild instanceof RecyclerView)) return; - final var recyclerView = (RecyclerView) layoutChild; - - recyclerView.getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - try { - listener.recyclerOnGlobalLayout(recyclerView); - } catch (Exception ex) { - LogHelper.printException(() -> "addRecyclerListener failure", ex); - } finally { - // Remove the listener because it will be added again. - recyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(this); - } - } - } - ); - } - - public interface RecyclerViewGlobalLayoutListener { - void recyclerOnGlobalLayout(@NonNull RecyclerView recyclerView); - } - - @Deprecated(message = "This patch is deprecated because the quality menu is not a ListView anymore") + /** + * Injection point. Only used if spoofing to an old app version. + */ public static void showOldVideoQualityMenu(final ListView listView) { if (!SettingsEnum.SHOW_OLD_VIDEO_QUALITY_MENU.getBoolean()) return; diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java index a65a2530f6..5e3185787c 100644 --- a/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/playback/speed/CustomPlaybackSpeedPatch.java @@ -1,23 +1,23 @@ package app.revanced.integrations.patches.playback.speed; import android.preference.ListPreference; +import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.ViewGroup; -import android.widget.LinearLayout; + import androidx.annotation.NonNull; + +import java.util.Arrays; + import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; -import com.facebook.litho.ComponentHost; - -import java.util.Arrays; - -import static app.revanced.integrations.patches.playback.quality.OldVideoQualityMenuPatch.addRecyclerListener; public class CustomPlaybackSpeedPatch { /** * Maximum playback speed, exclusive value. Custom speeds must be less than this value. + * Limit is required otherwise double digit speeds show up out of order in the UI selector. */ public static final float MAXIMUM_PLAYBACK_SPEED = 10; @@ -26,16 +26,6 @@ public class CustomPlaybackSpeedPatch { */ public static float[] customPlaybackSpeeds; - /** - * Minimum value of {@link #customPlaybackSpeeds} - */ - public static float minPlaybackSpeed; - - /** - * Maxium value of {@link #customPlaybackSpeeds} - */ - public static float maxPlaybackSpeed; - /** * PreferenceList entries and values, of all available playback speeds. */ @@ -69,8 +59,6 @@ private static void loadCustomSpeeds() { loadCustomSpeeds(); return; } - minPlaybackSpeed = Math.min(minPlaybackSpeed, speed); - maxPlaybackSpeed = Math.max(maxPlaybackSpeed, speed); customPlaybackSpeeds[i] = speed; } } catch (Exception ex) { @@ -106,25 +94,37 @@ public static void initializeListPreference(ListPreference preference) { preference.setEntryValues(preferenceListEntryValues); } - /* - * To reduce copy and paste between two similar code paths. + /** + * Injection point. */ - public static void onFlyoutMenuCreate(final LinearLayout linearLayout) { - // The playback rate menu is a RecyclerView with 2 children. The third child is the "Advanced" quality menu. - addRecyclerListener(linearLayout, 2, 1, recyclerView -> { - if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible) { - PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false; - - if (recyclerView.getChildCount() == 1 && recyclerView.getChildAt(0) instanceof ComponentHost) { - linearLayout.setVisibility(View.GONE); - - // Close the new Playback speed menu and instead show the old one. + public static void onFlyoutMenuCreate(RecyclerView recyclerView) { + recyclerView.getViewTreeObserver().addOnDrawListener(() -> { + try { + // For some reason, the custom playback speed flyout panel is activated when the user opens the share panel. (A/B tests) + // Check the child count of playback speed flyout panel to prevent this issue. + // Child count of playback speed flyout panel is always 8. + if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible + && ((ViewGroup) recyclerView.getChildAt(0)).getChildCount() == 8) { + PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible = false; + ViewGroup parentView3rd = (ViewGroup) recyclerView.getParent().getParent().getParent(); + ViewGroup parentView4th = (ViewGroup) parentView3rd.getParent(); + + // Dismiss View [R.id.touch_outside] is the 1st ChildView of the 4th ParentView. + // This only shows in phone layout. + parentView4th.getChildAt(0).performClick(); + + // In tablet layout there is no Dismiss View, instead we just hide all two parent views. + parentView3rd.setVisibility(View.GONE); + parentView4th.setVisibility(View.GONE); + + // This works without issues for both tablet and phone layouts, + // So no code is needed to check whether the current device is a tablet or phone. + + // Close the new Playback speed menu and show the old one. showOldPlaybackSpeedMenu(); - - // DismissView [R.id.touch_outside] is the 1st ChildView of the 3rd ParentView. - ((ViewGroup) linearLayout.getParent().getParent().getParent()) - .getChildAt(0).performClick(); } + } catch (Exception ex) { + LogHelper.printException(() -> "onFlyoutMenuCreate failure", ex); } }); } diff --git a/dummy/src/main/java/com/facebook/litho/ComponentHost.java b/dummy/src/main/java/com/facebook/litho/ComponentHost.java deleted file mode 100644 index ea2cde3fd2..0000000000 --- a/dummy/src/main/java/com/facebook/litho/ComponentHost.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.facebook.litho; - -import android.content.Context; -import android.support.v7.widget.RecyclerView; - -public final class ComponentHost extends RecyclerView { - public ComponentHost(Context context) { - super(context); - } -} From 9272df52f3416a88a2d5740d0c3e0eca858bf74d Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 19 Sep 2023 02:26:25 +0000 Subject: [PATCH 13/69] chore(release): 0.118.0-dev.3 [skip ci] # [0.118.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.2...v0.118.0-dev.3) (2023-09-19) ### Bug Fixes * **YouTube:** fix old quality and custom speed not working on tablets ([#477](https://github.com/ReVanced/revanced-integrations/issues/477)) ([2352fa5](https://github.com/ReVanced/revanced-integrations/commit/2352fa542658035c5f4400fb5892217887710e4d)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85091da317..23d3505abb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.2...v0.118.0-dev.3) (2023-09-19) + + +### Bug Fixes + +* **YouTube:** fix old quality and custom speed not working on tablets ([#477](https://github.com/ReVanced/revanced-integrations/issues/477)) ([2352fa5](https://github.com/ReVanced/revanced-integrations/commit/2352fa542658035c5f4400fb5892217887710e4d)) + # [0.118.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.1...v0.118.0-dev.2) (2023-09-14) diff --git a/gradle.properties b/gradle.properties index 38ad933196..8e0deb2b88 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.2 +version = 0.118.0-dev.3 From b193b3dbc168ea1145178039418a284cb2f5430b Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 23 Sep 2023 18:17:45 +0200 Subject: [PATCH 14/69] ci: Use better workflow name and PR message --- .github/workflows/pull_request.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index fbee1c7937..2b123ec672 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,4 +1,4 @@ -name: PR to main +name: Open a PR to main on: push: @@ -7,7 +7,7 @@ on: workflow_dispatch: env: - MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main` + MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main` jobs: pull-request: From ef1cca02c165d9c24e64b43fae375ae57bf90a52 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sat, 23 Sep 2023 23:48:53 +0200 Subject: [PATCH 15/69] fix(YouTube - Client spoof): Do not record feed videos to history by default (#478) --- .../patches/SpoofSignaturePatch.java | 90 ++++++++++++++++++ .../SpoofSignatureVerificationPatch.java | 95 ------------------- .../integrations/settings/SettingsEnum.java | 6 +- 3 files changed, 94 insertions(+), 97 deletions(-) create mode 100644 app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java delete mode 100644 app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java new file mode 100644 index 0000000000..ca523a4d4d --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java @@ -0,0 +1,90 @@ +package app.revanced.integrations.patches; + +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.shared.PlayerType; +import app.revanced.integrations.utils.LogHelper; + +import static app.revanced.integrations.utils.ReVancedUtils.containsAny; + +/** @noinspection unused*/ +public class SpoofSignaturePatch { + /** + * Parameter (also used by + * yt-dlp) + * to fix playback issues. + */ + private static final String INCOGNITO_PARAMETERS = "CgIQBg=="; + + /** + * Parameters causing playback issues. + */ + private static final String[] AUTOPLAY_PARAMETERS = { + "YAHI", // Autoplay in feed. + "SAFg" // Autoplay in scrim. + }; + + /** + * Parameter used for autoplay in scrim. + * Prepend this parameter to mute video playback (for autoplay in feed). + */ + private static final String SCRIM_PARAMETER = "SAFgAXgB"; + + + /** + * Parameters used in YouTube Shorts. + */ + private static final String SHORTS_PLAYER_PARAMETERS = "8AEB"; + + private static boolean isPlayingShorts; + + /** + * Injection point. + * + * @param parameters Original protobuf parameter value. + */ + public static String spoofParameter(String parameters) { + LogHelper.printDebug(() -> "Original protobuf parameter value: " + parameters); + + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return parameters; + + // Shorts do not need to be spoofed. + //noinspection AssignmentUsedAsCondition + if (isPlayingShorts = parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; + + boolean isPlayingFeed = PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL && containsAny(parameters, AUTOPLAY_PARAMETERS); + if (isPlayingFeed) return SettingsEnum.SPOOF_SIGNATURE_IN_FEED.getBoolean() ? + // Prepend the scrim parameter to mute videos in feed. + SCRIM_PARAMETER + INCOGNITO_PARAMETERS : + // In order to prevent videos that are auto-played in feed to be added to history, + // only spoof the parameter if the video is not playing in the feed. + // This will cause playback issues in the feed, but it's better than manipulating the history. + parameters; + + return INCOGNITO_PARAMETERS; + } + + /** + * Injection point. + */ + public static boolean getSeekbarThumbnailOverrideValue() { + return SettingsEnum.SPOOF_SIGNATURE.getBoolean(); + } + + /** + * Injection point. + * + * @param view seekbar thumbnail view. Includes both shorts and regular videos. + */ + public static void seekbarImageViewCreated(ImageView view) { + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return; + if (isPlayingShorts) return; + + view.setVisibility(View.GONE); + // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). + ViewGroup parentLayout = (ViewGroup) view.getParent(); + parentLayout.setPadding(0, 0, 0, 0); + } +} diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java b/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java deleted file mode 100644 index 37c7a51dfa..0000000000 --- a/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java +++ /dev/null @@ -1,95 +0,0 @@ -package app.revanced.integrations.patches; - -import static app.revanced.integrations.utils.ReVancedUtils.containsAny; - -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; - -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.shared.PlayerType; -import app.revanced.integrations.utils.LogHelper; - -public class SpoofSignatureVerificationPatch { - /** - * Enable/disable all workarounds that are required due to signature spoofing. - */ - private static final boolean WORKAROUND = true; - - /** - * Protobuf parameters used for autoplay in scrim. - * Prepend this parameter to mute video playback (for autoplay in feed) - */ - private static final String PROTOBUF_PARAMETER_SCRIM = "SAFgAXgB"; - - /** - * Protobuf parameter also used by - * yt-dlp - *
- * Known issue: captions are positioned on upper area in the player. - */ - private static final String PROTOBUF_PLAYER_PARAMS = "CgIQBg=="; - - /** - * Target Protobuf parameters. - */ - private static final String[] PROTOBUF_PARAMETER_TARGETS = { - "YAHI", // Autoplay in feed - "SAFg" // Autoplay in scrim - }; - - /** - * Injection point. - * - * @param originalValue originalValue protobuf parameter - */ - public static String overrideProtobufParameter(String originalValue) { - try { - if (!SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { - return originalValue; - } - - LogHelper.printDebug(() -> "Original protobuf parameter value: " + originalValue); - - if (!WORKAROUND) return PROTOBUF_PLAYER_PARAMS; - - var isPlayingVideo = originalValue.contains(PROTOBUF_PLAYER_PARAMS); - if (isPlayingVideo) return originalValue; - - boolean isPlayingFeed = containsAny(originalValue, PROTOBUF_PARAMETER_TARGETS) && PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL; - if (isPlayingFeed) { - // Videos in feed won't autoplay with sound. - return PROTOBUF_PARAMETER_SCRIM + PROTOBUF_PLAYER_PARAMS; - } else { - // Spoof the parameter to prevent playback issues. - return PROTOBUF_PLAYER_PARAMS; - } - } catch (Exception ex) { - LogHelper.printException(() -> "overrideProtobufParameter failure", ex); - } - - return originalValue; - } - - /** - * Injection point. - */ - public static boolean getSeekbarThumbnailOverrideValue() { - return SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean(); - } - - /** - * Injection point. - * - * @param view seekbar thumbnail view. Includes both shorts and regular videos. - */ - public static void seekbarImageViewCreated(ImageView view) { - if (SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) { - view.setVisibility(View.GONE); - // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). - ViewGroup parentLayout = (ViewGroup) view.getParent(); - parentLayout.setPadding(0, 0, 0, 0); - } - } - -} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 7b578a630e..3ab42ddd6d 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -165,8 +165,10 @@ public enum SettingsEnum { EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true), AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE), SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE), - SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, true, - "revanced_spoof_signature_verification_user_dialog_message"), + SPOOF_SIGNATURE("revanced_spoof_signature_verification_enabled", BOOLEAN, TRUE, true, + "revanced_spoof_signature_verification_enabled_user_dialog_message"), + SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false, + parents(SPOOF_SIGNATURE)), // Swipe controls SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE), From bfae6b56ab0f145f26a13441a0da3e55487e5158 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sat, 23 Sep 2023 21:53:51 +0000 Subject: [PATCH 16/69] chore(release): 0.118.0-dev.4 [skip ci] # [0.118.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.3...v0.118.0-dev.4) (2023-09-23) ### Bug Fixes * **YouTube - Client spoof:** Do not record feed videos to history by default ([#478](https://github.com/ReVanced/revanced-integrations/issues/478)) ([ef1cca0](https://github.com/ReVanced/revanced-integrations/commit/ef1cca02c165d9c24e64b43fae375ae57bf90a52)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23d3505abb..0572e03058 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.3...v0.118.0-dev.4) (2023-09-23) + + +### Bug Fixes + +* **YouTube - Client spoof:** Do not record feed videos to history by default ([#478](https://github.com/ReVanced/revanced-integrations/issues/478)) ([ef1cca0](https://github.com/ReVanced/revanced-integrations/commit/ef1cca02c165d9c24e64b43fae375ae57bf90a52)) + # [0.118.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.2...v0.118.0-dev.3) (2023-09-19) diff --git a/gradle.properties b/gradle.properties index 8e0deb2b88..0b4edafb6f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.3 +version = 0.118.0-dev.4 From 978f630c0267ec2b0d9bb9b5b0b3cdc9abef65ec Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 25 Sep 2023 16:28:23 +0200 Subject: [PATCH 17/69] fix(YouTube - Client spoof): Restore seekbar thumbnails This works around the issue, but causes seekbar thumbnails to be in low quality. --- .../{ => spoof}/SpoofSignaturePatch.java | 29 +++---- .../requests/StoryBoardRendererRequester.java | 79 +++++++++++++++++++ .../requests/StoryBoardRendererRoutes.java | 34 ++++++++ 3 files changed, 128 insertions(+), 14 deletions(-) rename app/src/main/java/app/revanced/integrations/patches/{ => spoof}/SpoofSignaturePatch.java (78%) create mode 100644 app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java create mode 100644 app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java similarity index 78% rename from app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java rename to app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index ca523a4d4d..09dbfd34a1 100644 --- a/app/src/main/java/app/revanced/integrations/patches/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -1,12 +1,11 @@ -package app.revanced.integrations.patches; +package app.revanced.integrations.patches.spoof; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; +import app.revanced.integrations.patches.VideoInformation; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.shared.PlayerType; import app.revanced.integrations.utils.LogHelper; +import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardsRenderer; import static app.revanced.integrations.utils.ReVancedUtils.containsAny; /** @noinspection unused*/ @@ -40,6 +39,8 @@ public class SpoofSignaturePatch { private static boolean isPlayingShorts; + private static String storyboardRendererSpec = ""; + /** * Injection point. * @@ -63,6 +64,7 @@ public static String spoofParameter(String parameters) { // This will cause playback issues in the feed, but it's better than manipulating the history. parameters; + fetchStoryboardsRenderer(VideoInformation.getVideoId()); return INCOGNITO_PARAMETERS; } @@ -75,16 +77,15 @@ public static boolean getSeekbarThumbnailOverrideValue() { /** * Injection point. - * - * @param view seekbar thumbnail view. Includes both shorts and regular videos. */ - public static void seekbarImageViewCreated(ImageView view) { - if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return; - if (isPlayingShorts) return; - - view.setVisibility(View.GONE); - // Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible). - ViewGroup parentLayout = (ViewGroup) view.getParent(); - parentLayout.setPadding(0, 0, 0, 0); + public static String getStoryboardRendererSpec() { + return storyboardRendererSpec; + } + + public static void setStoryboardRendererSpec(String newlyLoadedStoryboardRendererSpec) { + if (storyboardRendererSpec.equals(newlyLoadedStoryboardRendererSpec)) + return; + + storyboardRendererSpec = newlyLoadedStoryboardRendererSpec; } } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java new file mode 100644 index 0000000000..44f10f5e1c --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java @@ -0,0 +1,79 @@ +package app.revanced.integrations.patches.spoof.requests; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import app.revanced.integrations.patches.spoof.SpoofSignaturePatch; +import app.revanced.integrations.requests.Requester; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; +import org.json.JSONObject; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; + +public class StoryBoardRendererRequester { + private static final String INNER_TUBE_BODY = + "{" + + "\"context\": " + + "{" + + "\"client\": " + + "{ " + + "\"clientName\": \"ANDROID\", \"clientVersion\": \"18.37.36\", \"platform\": \"MOBILE\", " + + "\"osName\": \"Android\", \"osVersion\": \"12\", \"androidSdkVersion\": 31 " + + "} " + + "}, " + + "\"videoId\": \"%s\"" + + "}"; + + private StoryBoardRendererRequester() { + } + + // TODO: Find a way to increase the quality of SeekBar thumbnail previews + public static void fetchStoryboardsRenderer(@NonNull String videoId) { + ReVancedUtils.verifyOffMainThread(); + + try { + final byte[] innerTubeBody = String.format(INNER_TUBE_BODY, videoId).getBytes(StandardCharsets.UTF_8); + + HttpURLConnection connection = StoryBoardRendererRoutes.getPlayerResponseConnectionFromRoute(); + connection.getOutputStream().write(innerTubeBody, 0, innerTubeBody.length); + + final int responseCode = connection.getResponseCode(); + + if (responseCode == 200) { + final JSONObject playerResponse = Requester.parseJSONObject(connection); + + final JSONObject storyboards = playerResponse.getJSONObject("storyboards"); + final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer") + ? "playerLiveStoryboardSpecRenderer" + : "playerStoryboardSpecRenderer"; + final JSONObject storyboardsRenderer = storyboards.getJSONObject(storyboardsRendererTag); + final String storyboardsRendererSpec = storyboardsRenderer.getString("spec"); + + SpoofSignaturePatch.setStoryboardRendererSpec(storyboardsRendererSpec); + LogHelper.printDebug(() -> "StoryBoard renderer spec: " + storyboardsRendererSpec); + + } else { + handleConnectionError("API not available: " + responseCode, null); + } + connection.disconnect(); + } catch (SocketTimeoutException ex) { + handleConnectionError("API timed out", ex); + } catch (IOException ex) { + handleConnectionError(String.format("Failed to fetch StoryBoard URL (%s)", ex.getMessage()), ex); + } catch (Exception ex) { + handleConnectionError("Failed to fetch StoryBoard URL", ex); + } + } + + private static void handleConnectionError(@NonNull String toastMessage, @Nullable Exception ex) { + if (ex != null) + LogHelper.printException(() -> toastMessage, ex); + else + LogHelper.printException(() -> toastMessage); + + SpoofSignaturePatch.setStoryboardRendererSpec(""); + } +} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java new file mode 100644 index 0000000000..f5fb11b6cc --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java @@ -0,0 +1,34 @@ +package app.revanced.integrations.patches.spoof.requests; + +import app.revanced.integrations.requests.Requester; +import app.revanced.integrations.requests.Route; + +import java.io.IOException; +import java.net.HttpURLConnection; + +/** @noinspection unused*/ +public final class StoryBoardRendererRoutes { + private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/"; + private static final String YT_API_KEY = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w"; + + static final Route GET_PLAYER_RESPONSE_BODY = new Route(Route.Method.POST, "player?key={api_key}"); + + private StoryBoardRendererRoutes() { + } + + public static HttpURLConnection getPlayerResponseConnectionFromRoute() throws IOException { + var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_PLAYER_RESPONSE_BODY, YT_API_KEY); + connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip"); + connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("Accept-Language", "en-GB, en;q=0.9"); + connection.setRequestProperty("Pragma", "no-cache"); + connection.setRequestProperty("Cache-Control", "no-cache"); + connection.setUseCaches(false); + connection.setDoOutput(true); + connection.setConnectTimeout(5000); + connection.setReadTimeout(5000); + return connection; + } + +} \ No newline at end of file From 2cd1738d2494add13c48b64ccc9aad2432b2d8e3 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 25 Sep 2023 16:33:06 +0200 Subject: [PATCH 18/69] fix(YouTube - Client spoof): Restore clipping videos functionality --- .../integrations/patches/spoof/SpoofSignaturePatch.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 09dbfd34a1..616f4cdcb4 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -51,6 +51,13 @@ public static String spoofParameter(String parameters) { if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return parameters; + // Clip's player parameters contain a lot of information (e.g. video start and end time or whether it loops) + // For this reason, the player parameters of a clip are usually very long (150~300 characters). + // Clips are 60 seconds or less in length, so no spoofing. + var isClip = parameters.length() > 150; + if (isClip) return parameters; + + // Shorts do not need to be spoofed. //noinspection AssignmentUsedAsCondition if (isPlayingShorts = parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; From a113905e5ccea3c39aa15c589759b08b2d2df51a Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Sep 2023 14:36:47 +0000 Subject: [PATCH 19/69] chore(release): 0.118.0-dev.5 [skip ci] # [0.118.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.4...v0.118.0-dev.5) (2023-09-25) ### Bug Fixes * **YouTube - Client spoof:** Restore clipping videos functionality ([2cd1738](https://github.com/ReVanced/revanced-integrations/commit/2cd1738d2494add13c48b64ccc9aad2432b2d8e3)) * **YouTube - Client spoof:** Restore seekbar thumbnails ([978f630](https://github.com/ReVanced/revanced-integrations/commit/978f630c0267ec2b0d9bb9b5b0b3cdc9abef65ec)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0572e03058..959fd08108 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [0.118.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.4...v0.118.0-dev.5) (2023-09-25) + + +### Bug Fixes + +* **YouTube - Client spoof:** Restore clipping videos functionality ([2cd1738](https://github.com/ReVanced/revanced-integrations/commit/2cd1738d2494add13c48b64ccc9aad2432b2d8e3)) +* **YouTube - Client spoof:** Restore seekbar thumbnails ([978f630](https://github.com/ReVanced/revanced-integrations/commit/978f630c0267ec2b0d9bb9b5b0b3cdc9abef65ec)) + # [0.118.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.3...v0.118.0-dev.4) (2023-09-23) diff --git a/gradle.properties b/gradle.properties index 0b4edafb6f..3c5df42a2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.4 +version = 0.118.0-dev.5 From d20b768bc23d167d9f0d2c651c75b3f92944e731 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 25 Sep 2023 19:47:07 +0200 Subject: [PATCH 20/69] perf: Only request required fields --- .../spoof/requests/StoryBoardRendererRoutes.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java index f5fb11b6cc..3af7a11e2a 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java @@ -11,13 +11,19 @@ public final class StoryBoardRendererRoutes { private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/"; private static final String YT_API_KEY = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w"; - static final Route GET_PLAYER_RESPONSE_BODY = new Route(Route.Method.POST, "player?key={api_key}"); + static final Route GET_STORYBOARD_SPEC = new Route( + Route.Method.POST, + "player" + + "?fields=storyboards.playerStoryboardSpecRenderer.spec," + + "storyboards.playerLiveStoryboardSpecRenderer.spec" + + "&key={api_key}" + ); private StoryBoardRendererRoutes() { } public static HttpURLConnection getPlayerResponseConnectionFromRoute() throws IOException { - var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_PLAYER_RESPONSE_BODY, YT_API_KEY); + var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_STORYBOARD_SPEC, YT_API_KEY); connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip"); connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); connection.setRequestProperty("Content-Type", "application/json"); From ba5e7d870ee88ad45c233d914e1e2795de920cb2 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 25 Sep 2023 19:57:53 +0200 Subject: [PATCH 21/69] perf: Remove unnecessary api key parameter --- .../patches/spoof/requests/StoryBoardRendererRoutes.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java index 3af7a11e2a..f0d7f49154 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java @@ -9,8 +9,6 @@ /** @noinspection unused*/ public final class StoryBoardRendererRoutes { private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/"; - private static final String YT_API_KEY = "AIzaSyA8eiZmM1FaDVjRy-df2KTyQ_vz_yYM39w"; - static final Route GET_STORYBOARD_SPEC = new Route( Route.Method.POST, "player" + @@ -23,7 +21,7 @@ private StoryBoardRendererRoutes() { } public static HttpURLConnection getPlayerResponseConnectionFromRoute() throws IOException { - var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_STORYBOARD_SPEC, YT_API_KEY); + var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_STORYBOARD_SPEC); connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip"); connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); connection.setRequestProperty("Content-Type", "application/json"); From aa0282f300f00b46c436715c58d8e19dd224c1f1 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Sep 2023 18:12:35 +0000 Subject: [PATCH 22/69] chore(release): 0.118.0-dev.6 [skip ci] # [0.118.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.5...v0.118.0-dev.6) (2023-09-25) ### Performance Improvements * Only request required fields ([d20b768](https://github.com/ReVanced/revanced-integrations/commit/d20b768bc23d167d9f0d2c651c75b3f92944e731)) * Remove unnecessary api key parameter ([ba5e7d8](https://github.com/ReVanced/revanced-integrations/commit/ba5e7d870ee88ad45c233d914e1e2795de920cb2)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 959fd08108..2f9d64ce51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [0.118.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.5...v0.118.0-dev.6) (2023-09-25) + + +### Performance Improvements + +* Only request required fields ([d20b768](https://github.com/ReVanced/revanced-integrations/commit/d20b768bc23d167d9f0d2c651c75b3f92944e731)) +* Remove unnecessary api key parameter ([ba5e7d8](https://github.com/ReVanced/revanced-integrations/commit/ba5e7d870ee88ad45c233d914e1e2795de920cb2)) + # [0.118.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.4...v0.118.0-dev.5) (2023-09-25) diff --git a/gradle.properties b/gradle.properties index 3c5df42a2b..48bf09e3da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.5 +version = 0.118.0-dev.6 From 4b0925e33762c02e95ef9b1aadcae1038af71a50 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 25 Sep 2023 21:46:06 +0200 Subject: [PATCH 23/69] fix: Remove parameter from route --- .../patches/spoof/requests/StoryBoardRendererRoutes.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java index f0d7f49154..f78ab96ff8 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java @@ -13,8 +13,7 @@ public final class StoryBoardRendererRoutes { Route.Method.POST, "player" + "?fields=storyboards.playerStoryboardSpecRenderer.spec," + - "storyboards.playerLiveStoryboardSpecRenderer.spec" + - "&key={api_key}" + "storyboards.playerLiveStoryboardSpecRenderer.spec" ); private StoryBoardRendererRoutes() { From b76794b08ccfea9b81fe8f872231bf6756098aee Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Sep 2023 19:52:03 +0000 Subject: [PATCH 24/69] chore(release): 0.118.0-dev.7 [skip ci] # [0.118.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.6...v0.118.0-dev.7) (2023-09-25) ### Bug Fixes * Remove parameter from route ([4b0925e](https://github.com/ReVanced/revanced-integrations/commit/4b0925e33762c02e95ef9b1aadcae1038af71a50)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f9d64ce51..bdc043218d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.6...v0.118.0-dev.7) (2023-09-25) + + +### Bug Fixes + +* Remove parameter from route ([4b0925e](https://github.com/ReVanced/revanced-integrations/commit/4b0925e33762c02e95ef9b1aadcae1038af71a50)) + # [0.118.0-dev.6](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.5...v0.118.0-dev.6) (2023-09-25) diff --git a/gradle.properties b/gradle.properties index 48bf09e3da..71186d1c4a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.6 +version = 0.118.0-dev.7 From f71c1a0c156b2320e06dd98b3e5b276560d438aa Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 25 Sep 2023 23:50:41 +0200 Subject: [PATCH 25/69] fix(YouTube - Client spoof): Display seekbar thumbnails in high quality --- .../patches/spoof/SpoofSignaturePatch.java | 22 +++++++++++++++---- .../requests/StoryBoardRendererRequester.java | 2 ++ .../requests/StoryBoardRendererRoutes.java | 4 ++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 616f4cdcb4..fc08ad1a91 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -40,6 +40,7 @@ public class SpoofSignaturePatch { private static boolean isPlayingShorts; private static String storyboardRendererSpec = ""; + private static int recommendedLevel; /** * Injection point. @@ -82,17 +83,30 @@ public static boolean getSeekbarThumbnailOverrideValue() { return SettingsEnum.SPOOF_SIGNATURE.getBoolean(); } + /** * Injection point. */ - public static String getStoryboardRendererSpec() { + public static String getStoryboardRendererSpec(String originalStoryboardRendererSpec) { + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalStoryboardRendererSpec; + return storyboardRendererSpec; } - public static void setStoryboardRendererSpec(String newlyLoadedStoryboardRendererSpec) { - if (storyboardRendererSpec.equals(newlyLoadedStoryboardRendererSpec)) - return; + /** + * Injection point. + */ + public static int getRecommendedLevel(int originalLevel) { + if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalLevel; + return recommendedLevel; + } + + public static void setStoryboardRendererSpec(String newlyLoadedStoryboardRendererSpec) { storyboardRendererSpec = newlyLoadedStoryboardRendererSpec; } + + public static void setRecommendedLevel(int level) { + recommendedLevel = level; + } } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java index 44f10f5e1c..1969e48b4c 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java @@ -53,6 +53,8 @@ public static void fetchStoryboardsRenderer(@NonNull String videoId) { final String storyboardsRendererSpec = storyboardsRenderer.getString("spec"); SpoofSignaturePatch.setStoryboardRendererSpec(storyboardsRendererSpec); + SpoofSignaturePatch.setRecommendedLevel(storyboardsRenderer.getInt("recommendedLevel")); + LogHelper.printDebug(() -> "StoryBoard renderer spec: " + storyboardsRendererSpec); } else { diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java index f78ab96ff8..7cd05768d1 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java @@ -12,8 +12,8 @@ public final class StoryBoardRendererRoutes { static final Route GET_STORYBOARD_SPEC = new Route( Route.Method.POST, "player" + - "?fields=storyboards.playerStoryboardSpecRenderer.spec," + - "storyboards.playerLiveStoryboardSpecRenderer.spec" + "?fields=storyboards.playerStoryboardSpecRenderer," + + "storyboards.playerLiveStoryboardSpecRenderer" ); private StoryBoardRendererRoutes() { From 89993619fdddc8d1653c63cab3f2e48c2cfd5920 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Sep 2023 21:55:32 +0000 Subject: [PATCH 26/69] chore(release): 0.118.0-dev.8 [skip ci] # [0.118.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.7...v0.118.0-dev.8) (2023-09-25) ### Bug Fixes * **YouTube - Client spoof:** Display seekbar thumbnails in high quality ([f71c1a0](https://github.com/ReVanced/revanced-integrations/commit/f71c1a0c156b2320e06dd98b3e5b276560d438aa)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdc043218d..db2d81ef28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.7...v0.118.0-dev.8) (2023-09-25) + + +### Bug Fixes + +* **YouTube - Client spoof:** Display seekbar thumbnails in high quality ([f71c1a0](https://github.com/ReVanced/revanced-integrations/commit/f71c1a0c156b2320e06dd98b3e5b276560d438aa)) + # [0.118.0-dev.7](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.6...v0.118.0-dev.7) (2023-09-25) diff --git a/gradle.properties b/gradle.properties index 71186d1c4a..9892e7ad64 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.7 +version = 0.118.0-dev.8 From e6903bff95b485d21773537bbcc162411b616618 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 26 Sep 2023 02:47:01 +0400 Subject: [PATCH 27/69] fix(YouTube - Client spoof): Removed unused code (#480) Co-authored-by: oSumAtrIX --- .../patches/spoof/SpoofSignaturePatch.java | 47 +++++++++++-------- .../patches/spoof/StoryboardRenderer.java | 32 +++++++++++++ ...dRendererRoutes.java => PlayerRoutes.java} | 14 +++--- .../requests/StoryBoardRendererRequester.java | 47 ++++++++----------- .../integrations/requests/Requester.java | 6 ++- 5 files changed, 92 insertions(+), 54 deletions(-) create mode 100644 app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java rename app/src/main/java/app/revanced/integrations/patches/spoof/requests/{StoryBoardRendererRoutes.java => PlayerRoutes.java} (75%) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index fc08ad1a91..a86f30b6d0 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -1,13 +1,15 @@ package app.revanced.integrations.patches.spoof; +import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardRenderer; +import static app.revanced.integrations.utils.ReVancedUtils.containsAny; + +import androidx.annotation.Nullable; + import app.revanced.integrations.patches.VideoInformation; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.shared.PlayerType; import app.revanced.integrations.utils.LogHelper; -import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardsRenderer; -import static app.revanced.integrations.utils.ReVancedUtils.containsAny; - /** @noinspection unused*/ public class SpoofSignaturePatch { /** @@ -31,16 +33,18 @@ public class SpoofSignaturePatch { */ private static final String SCRIM_PARAMETER = "SAFgAXgB"; - /** * Parameters used in YouTube Shorts. */ private static final String SHORTS_PLAYER_PARAMETERS = "8AEB"; - private static boolean isPlayingShorts; + /** + * Last video id loaded. Used to prevent reloading the same spec multiple times. + */ + private static volatile String currentVideoId; - private static String storyboardRendererSpec = ""; - private static int recommendedLevel; + @Nullable + private static volatile StoryboardRenderer renderer; /** * Injection point. @@ -60,8 +64,7 @@ public static String spoofParameter(String parameters) { // Shorts do not need to be spoofed. - //noinspection AssignmentUsedAsCondition - if (isPlayingShorts = parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; + if (parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; boolean isPlayingFeed = PlayerType.getCurrent() == PlayerType.INLINE_MINIMAL && containsAny(parameters, AUTOPLAY_PARAMETERS); if (isPlayingFeed) return SettingsEnum.SPOOF_SIGNATURE_IN_FEED.getBoolean() ? @@ -72,7 +75,13 @@ public static String spoofParameter(String parameters) { // This will cause playback issues in the feed, but it's better than manipulating the history. parameters; - fetchStoryboardsRenderer(VideoInformation.getVideoId()); + String videoId = VideoInformation.getVideoId(); + if (!videoId.equals(currentVideoId)) { + currentVideoId = videoId; + renderer = fetchStoryboardRenderer(videoId); + LogHelper.printDebug(() -> "Fetched: " + renderer); + } + return INCOGNITO_PARAMETERS; } @@ -83,14 +92,18 @@ public static boolean getSeekbarThumbnailOverrideValue() { return SettingsEnum.SPOOF_SIGNATURE.getBoolean(); } - /** * Injection point. + * Called from background threads and from the main thread. */ + @Nullable public static String getStoryboardRendererSpec(String originalStoryboardRendererSpec) { if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalStoryboardRendererSpec; - return storyboardRendererSpec; + StoryboardRenderer currentRenderer = renderer; + if (currentRenderer == null) return originalStoryboardRendererSpec; + + return currentRenderer.getSpec(); } /** @@ -99,14 +112,10 @@ public static String getStoryboardRendererSpec(String originalStoryboardRenderer public static int getRecommendedLevel(int originalLevel) { if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalLevel; - return recommendedLevel; - } + StoryboardRenderer currentRenderer = renderer; + if (currentRenderer == null) return originalLevel; - public static void setStoryboardRendererSpec(String newlyLoadedStoryboardRendererSpec) { - storyboardRendererSpec = newlyLoadedStoryboardRendererSpec; + return currentRenderer.getRecommendedLevel(); } - public static void setRecommendedLevel(int level) { - recommendedLevel = level; - } } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java b/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java new file mode 100644 index 0000000000..c7ce43e57d --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java @@ -0,0 +1,32 @@ +package app.revanced.integrations.patches.spoof; + +import androidx.annotation.NonNull; +import org.jetbrains.annotations.NotNull; + +public final class StoryboardRenderer { + private final String spec; + private final int recommendedLevel; + + public StoryboardRenderer(String spec, int recommendedLevel) { + this.spec = spec; + this.recommendedLevel = recommendedLevel; + } + + @NonNull + public String getSpec() { + return spec; + } + + public int getRecommendedLevel() { + return recommendedLevel; + } + + @NotNull + @Override + public String toString() { + return "StoryboardRenderer{" + + "spec='" + spec + '\'' + + ", recommendedLevel=" + recommendedLevel + + '}'; + } +} diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java similarity index 75% rename from app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java rename to app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java index 7cd05768d1..e6b7a1f6d3 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java @@ -6,21 +6,21 @@ import java.io.IOException; import java.net.HttpURLConnection; -/** @noinspection unused*/ -public final class StoryBoardRendererRoutes { +final class PlayerRoutes { private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/"; - static final Route GET_STORYBOARD_SPEC = new Route( + static final Route.CompiledRoute POST_STORYBOARD_SPEC_RENDERER = new Route( Route.Method.POST, "player" + "?fields=storyboards.playerStoryboardSpecRenderer," + "storyboards.playerLiveStoryboardSpecRenderer" - ); + ).compile(); - private StoryBoardRendererRoutes() { + private PlayerRoutes() { } - public static HttpURLConnection getPlayerResponseConnectionFromRoute() throws IOException { - var connection = Requester.getConnectionFromRoute(YT_API_URL, GET_STORYBOARD_SPEC); + /** @noinspection SameParameterValue*/ + static HttpURLConnection getPlayerResponseConnectionFromRoute(Route.CompiledRoute route) throws IOException { + var connection = Requester.getConnectionFromCompiledRoute(YT_API_URL, route); connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip"); connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); connection.setRequestProperty("Content-Type", "application/json"); diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java index 1969e48b4c..4e8dcddba9 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java @@ -2,16 +2,18 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.revanced.integrations.patches.spoof.SpoofSignaturePatch; +import app.revanced.integrations.patches.spoof.StoryboardRenderer; import app.revanced.integrations.requests.Requester; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; import org.json.JSONObject; -import java.io.IOException; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import static app.revanced.integrations.patches.spoof.requests.PlayerRoutes.POST_STORYBOARD_SPEC_RENDERER; public class StoryBoardRendererRequester { private static final String INNER_TUBE_BODY = @@ -30,14 +32,15 @@ public class StoryBoardRendererRequester { private StoryBoardRendererRequester() { } - // TODO: Find a way to increase the quality of SeekBar thumbnail previews - public static void fetchStoryboardsRenderer(@NonNull String videoId) { - ReVancedUtils.verifyOffMainThread(); - + @Nullable + public static StoryboardRenderer fetchStoryboardRenderer(@NonNull String videoId) { try { + ReVancedUtils.verifyOffMainThread(); + Objects.requireNonNull(videoId); + final byte[] innerTubeBody = String.format(INNER_TUBE_BODY, videoId).getBytes(StandardCharsets.UTF_8); - HttpURLConnection connection = StoryBoardRendererRoutes.getPlayerResponseConnectionFromRoute(); + HttpURLConnection connection = PlayerRoutes.getPlayerResponseConnectionFromRoute(POST_STORYBOARD_SPEC_RENDERER); connection.getOutputStream().write(innerTubeBody, 0, innerTubeBody.length); final int responseCode = connection.getResponseCode(); @@ -49,33 +52,23 @@ public static void fetchStoryboardsRenderer(@NonNull String videoId) { final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer") ? "playerLiveStoryboardSpecRenderer" : "playerStoryboardSpecRenderer"; - final JSONObject storyboardsRenderer = storyboards.getJSONObject(storyboardsRendererTag); - final String storyboardsRendererSpec = storyboardsRenderer.getString("spec"); - SpoofSignaturePatch.setStoryboardRendererSpec(storyboardsRendererSpec); - SpoofSignaturePatch.setRecommendedLevel(storyboardsRenderer.getInt("recommendedLevel")); - - LogHelper.printDebug(() -> "StoryBoard renderer spec: " + storyboardsRendererSpec); + final var renderer = storyboards.getJSONObject(storyboardsRendererTag); + return new StoryboardRenderer( + renderer.getString("spec"), + renderer.getInt("recommendedLevel") + ); } else { - handleConnectionError("API not available: " + responseCode, null); + LogHelper.printException(() -> "API not available: " + responseCode); + connection.disconnect(); } - connection.disconnect(); } catch (SocketTimeoutException ex) { - handleConnectionError("API timed out", ex); - } catch (IOException ex) { - handleConnectionError(String.format("Failed to fetch StoryBoard URL (%s)", ex.getMessage()), ex); + LogHelper.printException(() -> "API timed out", ex); } catch (Exception ex) { - handleConnectionError("Failed to fetch StoryBoard URL", ex); + LogHelper.printException(() -> "Failed to fetch StoryBoard URL", ex); } - } - - private static void handleConnectionError(@NonNull String toastMessage, @Nullable Exception ex) { - if (ex != null) - LogHelper.printException(() -> toastMessage, ex); - else - LogHelper.printException(() -> toastMessage); - SpoofSignaturePatch.setStoryboardRendererSpec(""); + return null; } } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/requests/Requester.java b/app/src/main/java/app/revanced/integrations/requests/Requester.java index 55b777d9bc..c756dfe855 100644 --- a/app/src/main/java/app/revanced/integrations/requests/Requester.java +++ b/app/src/main/java/app/revanced/integrations/requests/Requester.java @@ -16,7 +16,11 @@ private Requester() { } public static HttpURLConnection getConnectionFromRoute(String apiUrl, Route route, String... params) throws IOException { - String url = apiUrl + route.compile(params).getCompiledRoute(); + return getConnectionFromCompiledRoute(apiUrl, route.compile(params)); + } + + public static HttpURLConnection getConnectionFromCompiledRoute(String apiUrl, Route.CompiledRoute route) throws IOException { + String url = apiUrl + route.getCompiledRoute(); HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod(route.getMethod().name()); connection.setRequestProperty("User-agent", System.getProperty("http.agent") + ";revanced"); From a591c62543d14169a68e54e1d2de1b515edbf853 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 25 Sep 2023 22:50:24 +0000 Subject: [PATCH 28/69] chore(release): 0.118.0-dev.9 [skip ci] # [0.118.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.8...v0.118.0-dev.9) (2023-09-25) ### Bug Fixes * **YouTube - Client spoof:** Removed unused code ([#480](https://github.com/ReVanced/revanced-integrations/issues/480)) ([e6903bf](https://github.com/ReVanced/revanced-integrations/commit/e6903bff95b485d21773537bbcc162411b616618)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db2d81ef28..7d75dcc316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.8...v0.118.0-dev.9) (2023-09-25) + + +### Bug Fixes + +* **YouTube - Client spoof:** Removed unused code ([#480](https://github.com/ReVanced/revanced-integrations/issues/480)) ([e6903bf](https://github.com/ReVanced/revanced-integrations/commit/e6903bff95b485d21773537bbcc162411b616618)) + # [0.118.0-dev.8](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.7...v0.118.0-dev.8) (2023-09-25) diff --git a/gradle.properties b/gradle.properties index 9892e7ad64..560867e3cb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.8 +version = 0.118.0-dev.9 From 83987747e67541cd44221ede8c4020baba36c7b8 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 26 Sep 2023 05:09:01 +0400 Subject: [PATCH 29/69] fix(YouTube - Client spoof): fix storyboard fetched out of order (#481) --- .../patches/spoof/SpoofSignaturePatch.java | 39 ++++++++++++++----- .../requests/StoryBoardRendererRequester.java | 11 +++--- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index a86f30b6d0..b84c6636a3 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -5,10 +5,16 @@ import androidx.annotation.Nullable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + import app.revanced.integrations.patches.VideoInformation; import app.revanced.integrations.settings.SettingsEnum; import app.revanced.integrations.shared.PlayerType; import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; /** @noinspection unused*/ public class SpoofSignaturePatch { @@ -43,8 +49,7 @@ public class SpoofSignaturePatch { */ private static volatile String currentVideoId; - @Nullable - private static volatile StoryboardRenderer renderer; + private static volatile Future rendererFuture; /** * Injection point. @@ -78,13 +83,27 @@ public static String spoofParameter(String parameters) { String videoId = VideoInformation.getVideoId(); if (!videoId.equals(currentVideoId)) { currentVideoId = videoId; - renderer = fetchStoryboardRenderer(videoId); - LogHelper.printDebug(() -> "Fetched: " + renderer); + rendererFuture = ReVancedUtils.submitOnBackgroundThread(() -> fetchStoryboardRenderer(videoId)); } return INCOGNITO_PARAMETERS; } + @Nullable + private static StoryboardRenderer getRenderer() { + if (rendererFuture != null) { + try { + return rendererFuture.get(5000, TimeUnit.MILLISECONDS); + } catch (TimeoutException ex) { + LogHelper.printDebug(() -> "Could not get renderer (get timed out)"); + } catch (ExecutionException | InterruptedException ex) { + // Should never happen. + LogHelper.printException(() -> "Could not get renderer", ex); + } + } + return null; + } + /** * Injection point. */ @@ -100,10 +119,10 @@ public static boolean getSeekbarThumbnailOverrideValue() { public static String getStoryboardRendererSpec(String originalStoryboardRendererSpec) { if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalStoryboardRendererSpec; - StoryboardRenderer currentRenderer = renderer; - if (currentRenderer == null) return originalStoryboardRendererSpec; + StoryboardRenderer renderer = getRenderer(); + if (renderer == null) return originalStoryboardRendererSpec; - return currentRenderer.getSpec(); + return renderer.getSpec(); } /** @@ -112,10 +131,10 @@ public static String getStoryboardRendererSpec(String originalStoryboardRenderer public static int getRecommendedLevel(int originalLevel) { if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalLevel; - StoryboardRenderer currentRenderer = renderer; - if (currentRenderer == null) return originalLevel; + StoryboardRenderer renderer = getRenderer(); + if (renderer == null) return originalLevel; - return currentRenderer.getRecommendedLevel(); + return renderer.getRecommendedLevel(); } } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java index 4e8dcddba9..38369d8167 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java @@ -53,12 +53,13 @@ public static StoryboardRenderer fetchStoryboardRenderer(@NonNull String videoId ? "playerLiveStoryboardSpecRenderer" : "playerStoryboardSpecRenderer"; - final var renderer = storyboards.getJSONObject(storyboardsRendererTag); - - return new StoryboardRenderer( - renderer.getString("spec"), - renderer.getInt("recommendedLevel") + final var rendererElement = storyboards.getJSONObject(storyboardsRendererTag); + StoryboardRenderer renderer = new StoryboardRenderer( + rendererElement.getString("spec"), + rendererElement.getInt("recommendedLevel") ); + LogHelper.printDebug(() -> "Fetched: " + renderer); + return renderer; } else { LogHelper.printException(() -> "API not available: " + responseCode); connection.disconnect(); From 245265587a28dacdfd118a50612b9bab00c3da59 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Sep 2023 01:13:00 +0000 Subject: [PATCH 30/69] chore(release): 0.118.0-dev.10 [skip ci] # [0.118.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.9...v0.118.0-dev.10) (2023-09-26) ### Bug Fixes * **YouTube - Client spoof:** fix storyboard fetched out of order ([#481](https://github.com/ReVanced/revanced-integrations/issues/481)) ([8398774](https://github.com/ReVanced/revanced-integrations/commit/83987747e67541cd44221ede8c4020baba36c7b8)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d75dcc316..7fffc0713e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.9...v0.118.0-dev.10) (2023-09-26) + + +### Bug Fixes + +* **YouTube - Client spoof:** fix storyboard fetched out of order ([#481](https://github.com/ReVanced/revanced-integrations/issues/481)) ([8398774](https://github.com/ReVanced/revanced-integrations/commit/83987747e67541cd44221ede8c4020baba36c7b8)) + # [0.118.0-dev.9](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.8...v0.118.0-dev.9) (2023-09-25) diff --git a/gradle.properties b/gradle.properties index 560867e3cb..ae9a94970e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.9 +version = 0.118.0-dev.10 From e72b65b599353715a6467463226abc603bc850f7 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 26 Sep 2023 05:39:44 +0400 Subject: [PATCH 31/69] fix(YouTube - Client spoof): fix toast shown if opening paid or age restricted video (#482) --- .../patches/spoof/requests/StoryBoardRendererRequester.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java index 38369d8167..2f4f6518cb 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java @@ -48,6 +48,11 @@ public static StoryboardRenderer fetchStoryboardRenderer(@NonNull String videoId if (responseCode == 200) { final JSONObject playerResponse = Requester.parseJSONObject(connection); + if (!playerResponse.has("storyboards")) { + // Video is age restricted or paid. + LogHelper.printDebug(() -> "Video has no public storyboard: " + videoId); + return null; + } final JSONObject storyboards = playerResponse.getJSONObject("storyboards"); final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer") ? "playerLiveStoryboardSpecRenderer" From 62f92c38c1be1a3f3a6753c03f7d546c6c544e30 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Sep 2023 01:43:27 +0000 Subject: [PATCH 32/69] chore(release): 0.118.0-dev.11 [skip ci] # [0.118.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.10...v0.118.0-dev.11) (2023-09-26) ### Bug Fixes * **YouTube - Client spoof:** fix toast shown if opening paid or age restricted video ([#482](https://github.com/ReVanced/revanced-integrations/issues/482)) ([e72b65b](https://github.com/ReVanced/revanced-integrations/commit/e72b65b599353715a6467463226abc603bc850f7)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fffc0713e..85b056121b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.10...v0.118.0-dev.11) (2023-09-26) + + +### Bug Fixes + +* **YouTube - Client spoof:** fix toast shown if opening paid or age restricted video ([#482](https://github.com/ReVanced/revanced-integrations/issues/482)) ([e72b65b](https://github.com/ReVanced/revanced-integrations/commit/e72b65b599353715a6467463226abc603bc850f7)) + # [0.118.0-dev.10](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.9...v0.118.0-dev.10) (2023-09-26) diff --git a/gradle.properties b/gradle.properties index ae9a94970e..75fc41591f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.10 +version = 0.118.0-dev.11 From 01019b09c1c106ed814b994dd8af558a18873c1d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 26 Sep 2023 04:43:12 +0200 Subject: [PATCH 33/69] fix(YouTube - Client spoof): Show seekbar thumbnail for age restricted and paid videos --- .../patches/spoof/SpoofSignaturePatch.java | 51 ++++---- .../patches/spoof/requests/PlayerRoutes.java | 64 +++++++++- .../requests/StoryBoardRendererRequester.java | 80 ------------- .../requests/StoryboardRendererRequester.java | 113 ++++++++++++++++++ 4 files changed, 197 insertions(+), 111 deletions(-) delete mode 100644 app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java create mode 100644 app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index b84c6636a3..452150e1b5 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -1,20 +1,19 @@ package app.revanced.integrations.patches.spoof; -import static app.revanced.integrations.patches.spoof.requests.StoryBoardRendererRequester.fetchStoryboardRenderer; -import static app.revanced.integrations.utils.ReVancedUtils.containsAny; - import androidx.annotation.Nullable; +import app.revanced.integrations.patches.VideoInformation; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.shared.PlayerType; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import app.revanced.integrations.patches.VideoInformation; -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.shared.PlayerType; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; +import static app.revanced.integrations.patches.spoof.requests.StoryboardRendererRequester.getStoryboardRenderer; +import static app.revanced.integrations.utils.ReVancedUtils.containsAny; /** @noinspection unused*/ public class SpoofSignaturePatch { @@ -51,6 +50,24 @@ public class SpoofSignaturePatch { private static volatile Future rendererFuture; + @Nullable + private static volatile StoryboardRenderer renderer; + + @Nullable + private static StoryboardRenderer getRenderer() { + if (rendererFuture != null) { + try { + return rendererFuture.get(5000, TimeUnit.MILLISECONDS); + } catch (TimeoutException ex) { + LogHelper.printDebug(() -> "Could not get renderer (get timed out)"); + } catch (ExecutionException | InterruptedException ex) { + // Should never happen. + LogHelper.printException(() -> "Could not get renderer", ex); + } + } + return null; + } + /** * Injection point. * @@ -83,27 +100,12 @@ public static String spoofParameter(String parameters) { String videoId = VideoInformation.getVideoId(); if (!videoId.equals(currentVideoId)) { currentVideoId = videoId; - rendererFuture = ReVancedUtils.submitOnBackgroundThread(() -> fetchStoryboardRenderer(videoId)); + rendererFuture = ReVancedUtils.submitOnBackgroundThread(() -> getStoryboardRenderer(videoId)); } return INCOGNITO_PARAMETERS; } - @Nullable - private static StoryboardRenderer getRenderer() { - if (rendererFuture != null) { - try { - return rendererFuture.get(5000, TimeUnit.MILLISECONDS); - } catch (TimeoutException ex) { - LogHelper.printDebug(() -> "Could not get renderer (get timed out)"); - } catch (ExecutionException | InterruptedException ex) { - // Should never happen. - LogHelper.printException(() -> "Could not get renderer", ex); - } - } - return null; - } - /** * Injection point. */ @@ -136,5 +138,4 @@ public static int getRecommendedLevel(int originalLevel) { return renderer.getRecommendedLevel(); } - } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java index e6b7a1f6d3..db3971ba6a 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/PlayerRoutes.java @@ -2,19 +2,73 @@ import app.revanced.integrations.requests.Requester; import app.revanced.integrations.requests.Route; +import app.revanced.integrations.utils.LogHelper; +import org.json.JSONException; +import org.json.JSONObject; import java.io.IOException; import java.net.HttpURLConnection; final class PlayerRoutes { private static final String YT_API_URL = "https://www.youtube.com/youtubei/v1/"; - static final Route.CompiledRoute POST_STORYBOARD_SPEC_RENDERER = new Route( + static final Route.CompiledRoute GET_STORYBOARD_SPEC_RENDERER = new Route( Route.Method.POST, "player" + "?fields=storyboards.playerStoryboardSpecRenderer," + - "storyboards.playerLiveStoryboardSpecRenderer" + "storyboards.playerLiveStoryboardSpecRenderer," + + "playabilityStatus.status" ).compile(); + static final String ANDROID_INNER_TUBE_BODY; + static final String TV_EMBED_INNER_TUBE_BODY; + + static { + JSONObject innerTubeBody = new JSONObject(); + + try { + JSONObject context = new JSONObject(); + + JSONObject client = new JSONObject(); + client.put("clientName", "ANDROID"); + client.put("clientVersion", "18.37.36"); + client.put("androidSdkVersion", 34); + + context.put("client", client); + + innerTubeBody.put("context", context); + innerTubeBody.put("videoId", "%s"); + } catch (JSONException e) { + LogHelper.printException(() -> "Failed to create innerTubeBody", e); + } + + ANDROID_INNER_TUBE_BODY = innerTubeBody.toString(); + + JSONObject tvEmbedInnerTubeBody = new JSONObject(); + + try { + JSONObject context = new JSONObject(); + + JSONObject client = new JSONObject(); + client.put("clientName", "TVHTML5_SIMPLY_EMBEDDED_PLAYER"); + client.put("clientVersion", "2.0"); + client.put("platform", "TV"); + client.put("clientScreen", "EMBED"); + + JSONObject thirdParty = new JSONObject(); + thirdParty.put("embedUrl", "https://www.youtube.com/watch?v=%s"); + + context.put("thirdParty", thirdParty); + context.put("client", client); + + tvEmbedInnerTubeBody.put("context", context); + tvEmbedInnerTubeBody.put("videoId", "%s"); + } catch (JSONException e) { + LogHelper.printException(() -> "Failed to create tvEmbedInnerTubeBody", e); + } + + TV_EMBED_INNER_TUBE_BODY = tvEmbedInnerTubeBody.toString(); + } + private PlayerRoutes() { } @@ -24,14 +78,12 @@ static HttpURLConnection getPlayerResponseConnectionFromRoute(Route.CompiledRout connection.setRequestProperty("User-Agent", "com.google.android.youtube/18.37.36 (Linux; U; Android 12; GB) gzip"); connection.setRequestProperty("X-Goog-Api-Format-Version", "2"); connection.setRequestProperty("Content-Type", "application/json"); - connection.setRequestProperty("Accept-Language", "en-GB, en;q=0.9"); - connection.setRequestProperty("Pragma", "no-cache"); - connection.setRequestProperty("Cache-Control", "no-cache"); + connection.setUseCaches(false); connection.setDoOutput(true); + connection.setConnectTimeout(5000); connection.setReadTimeout(5000); return connection; } - } \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java deleted file mode 100644 index 2f4f6518cb..0000000000 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryBoardRendererRequester.java +++ /dev/null @@ -1,80 +0,0 @@ -package app.revanced.integrations.patches.spoof.requests; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import app.revanced.integrations.patches.spoof.StoryboardRenderer; -import app.revanced.integrations.requests.Requester; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; -import org.json.JSONObject; - -import java.net.HttpURLConnection; -import java.net.SocketTimeoutException; -import java.nio.charset.StandardCharsets; -import java.util.Objects; - -import static app.revanced.integrations.patches.spoof.requests.PlayerRoutes.POST_STORYBOARD_SPEC_RENDERER; - -public class StoryBoardRendererRequester { - private static final String INNER_TUBE_BODY = - "{" + - "\"context\": " + - "{" + - "\"client\": " + - "{ " + - "\"clientName\": \"ANDROID\", \"clientVersion\": \"18.37.36\", \"platform\": \"MOBILE\", " + - "\"osName\": \"Android\", \"osVersion\": \"12\", \"androidSdkVersion\": 31 " + - "} " + - "}, " + - "\"videoId\": \"%s\"" + - "}"; - - private StoryBoardRendererRequester() { - } - - @Nullable - public static StoryboardRenderer fetchStoryboardRenderer(@NonNull String videoId) { - try { - ReVancedUtils.verifyOffMainThread(); - Objects.requireNonNull(videoId); - - final byte[] innerTubeBody = String.format(INNER_TUBE_BODY, videoId).getBytes(StandardCharsets.UTF_8); - - HttpURLConnection connection = PlayerRoutes.getPlayerResponseConnectionFromRoute(POST_STORYBOARD_SPEC_RENDERER); - connection.getOutputStream().write(innerTubeBody, 0, innerTubeBody.length); - - final int responseCode = connection.getResponseCode(); - - if (responseCode == 200) { - final JSONObject playerResponse = Requester.parseJSONObject(connection); - - if (!playerResponse.has("storyboards")) { - // Video is age restricted or paid. - LogHelper.printDebug(() -> "Video has no public storyboard: " + videoId); - return null; - } - final JSONObject storyboards = playerResponse.getJSONObject("storyboards"); - final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer") - ? "playerLiveStoryboardSpecRenderer" - : "playerStoryboardSpecRenderer"; - - final var rendererElement = storyboards.getJSONObject(storyboardsRendererTag); - StoryboardRenderer renderer = new StoryboardRenderer( - rendererElement.getString("spec"), - rendererElement.getInt("recommendedLevel") - ); - LogHelper.printDebug(() -> "Fetched: " + renderer); - return renderer; - } else { - LogHelper.printException(() -> "API not available: " + responseCode); - connection.disconnect(); - } - } catch (SocketTimeoutException ex) { - LogHelper.printException(() -> "API timed out", ex); - } catch (Exception ex) { - LogHelper.printException(() -> "Failed to fetch StoryBoard URL", ex); - } - - return null; - } -} \ No newline at end of file diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java new file mode 100644 index 0000000000..105772eff9 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java @@ -0,0 +1,113 @@ +package app.revanced.integrations.patches.spoof.requests; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import app.revanced.integrations.patches.spoof.StoryboardRenderer; +import app.revanced.integrations.requests.Requester; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; +import org.json.JSONException; +import org.json.JSONObject; + +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.nio.charset.StandardCharsets; +import java.util.Objects; + +import static app.revanced.integrations.patches.spoof.requests.PlayerRoutes.*; + +public class StoryboardRendererRequester { + private StoryboardRendererRequester() { + } + + @Nullable + private static JSONObject fetchPlayerResponse(@NonNull String requestBody) { + try { + ReVancedUtils.verifyOffMainThread(); + Objects.requireNonNull(requestBody); + + final byte[] innerTubeBody = requestBody.getBytes(StandardCharsets.UTF_8); + + HttpURLConnection connection = PlayerRoutes.getPlayerResponseConnectionFromRoute(GET_STORYBOARD_SPEC_RENDERER); + connection.getOutputStream().write(innerTubeBody, 0, innerTubeBody.length); + + final int responseCode = connection.getResponseCode(); + if (responseCode == 200) return Requester.parseJSONObject(connection); + + LogHelper.printException(() -> "API not available: " + responseCode); + connection.disconnect(); + } catch (SocketTimeoutException ex) { + LogHelper.printException(() -> "API timed out", ex); + } catch (Exception ex) { + LogHelper.printException(() -> "Failed to fetch storyboard URL", ex); + } + + return null; + } + + private static boolean isPlayabilityStatusOk(@NonNull JSONObject playerResponse) { + try { + return playerResponse.getJSONObject("playabilityStatus").getString("status").equals("OK"); + } catch (JSONException e) { + LogHelper.printException(() -> "Failed to get playabilityStatus", e); + } + + return false; + } + + /** + * Fetches the storyboardRenderer from the innerTubeBody. + * @param innerTubeBody The innerTubeBody to use to fetch the storyboardRenderer. + * @return StoryboardRenderer or null if playabilityStatus is not OK. + */ + @Nullable + private static StoryboardRenderer getStoryboardRendererUsingBody(@NonNull String innerTubeBody) { + final JSONObject playerResponse = fetchPlayerResponse(innerTubeBody); + Objects.requireNonNull(playerResponse); + + if (isPlayabilityStatusOk(playerResponse)) return getStoryboardRendererUsingResponse(playerResponse); + + return null; + } + + @Nullable + private static StoryboardRenderer getStoryboardRendererUsingResponse(@NonNull JSONObject playerResponse) { + try { + final JSONObject storyboards = playerResponse.getJSONObject("storyboards"); + final String storyboardsRendererTag = storyboards.has("playerLiveStoryboardSpecRenderer") + ? "playerLiveStoryboardSpecRenderer" + : "playerStoryboardSpecRenderer"; + + final var rendererElement = storyboards.getJSONObject(storyboardsRendererTag); + StoryboardRenderer renderer = new StoryboardRenderer( + rendererElement.getString("spec"), + rendererElement.getInt("recommendedLevel") + ); + + LogHelper.printDebug(() -> "Fetched: " + renderer); + + return renderer; + } catch (JSONException e) { + LogHelper.printException(() -> "Failed to get storyboardRenderer", e); + } + + return null; + } + + @Nullable + public static StoryboardRenderer getStoryboardRenderer(@NonNull String videoId) { + try { + Objects.requireNonNull(videoId); + + var renderer = getStoryboardRendererUsingBody(String.format(ANDROID_INNER_TUBE_BODY, videoId)); + if (renderer == null) + renderer = getStoryboardRendererUsingBody(String.format(TV_EMBED_INNER_TUBE_BODY, videoId, videoId)); + + return renderer; + } catch (Exception ex) { + LogHelper.printException(() -> "Failed to fetch storyboard URL", ex); + } + + return null; + } +} \ No newline at end of file From 09e8b3e345c65486359f149346a58aa2a3a0348c Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 26 Sep 2023 02:53:16 +0000 Subject: [PATCH 34/69] chore(release): 0.118.0-dev.12 [skip ci] # [0.118.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.11...v0.118.0-dev.12) (2023-09-26) ### Bug Fixes * **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([01019b0](https://github.com/ReVanced/revanced-integrations/commit/01019b09c1c106ed814b994dd8af558a18873c1d)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85b056121b..9ded88acdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.11...v0.118.0-dev.12) (2023-09-26) + + +### Bug Fixes + +* **YouTube - Client spoof:** Show seekbar thumbnail for age restricted and paid videos ([01019b0](https://github.com/ReVanced/revanced-integrations/commit/01019b09c1c106ed814b994dd8af558a18873c1d)) + # [0.118.0-dev.11](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.10...v0.118.0-dev.11) (2023-09-26) diff --git a/gradle.properties b/gradle.properties index 75fc41591f..036d932c19 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.11 +version = 0.118.0-dev.12 From ab9989d41f64e1fe5b8eba4bda3bab3401504a63 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:05:25 +0400 Subject: [PATCH 35/69] chore(YouTube - Client spoof): add logging. fix fall over logic if android client call fails --- .../patches/spoof/SpoofSignaturePatch.java | 3 --- .../spoof/requests/StoryboardRendererRequester.java | 12 ++++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 452150e1b5..4c3fbaa672 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -50,9 +50,6 @@ public class SpoofSignaturePatch { private static volatile Future rendererFuture; - @Nullable - private static volatile StoryboardRenderer renderer; - @Nullable private static StoryboardRenderer getRenderer() { if (rendererFuture != null) { diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java index 105772eff9..d2b79e8dd6 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java @@ -63,9 +63,8 @@ private static boolean isPlayabilityStatusOk(@NonNull JSONObject playerResponse) @Nullable private static StoryboardRenderer getStoryboardRendererUsingBody(@NonNull String innerTubeBody) { final JSONObject playerResponse = fetchPlayerResponse(innerTubeBody); - Objects.requireNonNull(playerResponse); - - if (isPlayabilityStatusOk(playerResponse)) return getStoryboardRendererUsingResponse(playerResponse); + if (playerResponse != null && isPlayabilityStatusOk(playerResponse)) + return getStoryboardRendererUsingResponse(playerResponse); return null; } @@ -100,8 +99,13 @@ public static StoryboardRenderer getStoryboardRenderer(@NonNull String videoId) Objects.requireNonNull(videoId); var renderer = getStoryboardRendererUsingBody(String.format(ANDROID_INNER_TUBE_BODY, videoId)); - if (renderer == null) + if (renderer == null) { + LogHelper.printDebug(() -> videoId + " not available using android client"); renderer = getStoryboardRendererUsingBody(String.format(TV_EMBED_INNER_TUBE_BODY, videoId, videoId)); + if (renderer == null) { + LogHelper.printDebug(() -> videoId + " not available using tv embedded client"); + } + } return renderer; } catch (Exception ex) { From b0b6ff6a82820d4578c5cfc5f69ae7aaaac49c7f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Wed, 27 Sep 2023 18:54:47 +0400 Subject: [PATCH 36/69] fix(YouTube - Client spoof): fix occasionally frozen video playback (#486) --- .../integrations/patches/spoof/SpoofSignaturePatch.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 4c3fbaa672..69f00abfd6 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -68,6 +68,8 @@ private static StoryboardRenderer getRenderer() { /** * Injection point. * + * Called off the main thread, and called multiple times for each video. + * * @param parameters Original protobuf parameter value. */ public static String spoofParameter(String parameters) { @@ -96,9 +98,14 @@ public static String spoofParameter(String parameters) { String videoId = VideoInformation.getVideoId(); if (!videoId.equals(currentVideoId)) { - currentVideoId = videoId; rendererFuture = ReVancedUtils.submitOnBackgroundThread(() -> getStoryboardRenderer(videoId)); + currentVideoId = videoId; } + // Occasionally when a new video is opened the video will be frozen a few seconds while the audio plays. + // This is because the main thread is calling to get the storyboard but the fetch is not completed. + // To prevent this, call get() here and block until the fetch is completed. + // So later when the main thread calls to get the renderer it will never block as the future is done. + getRenderer(); return INCOGNITO_PARAMETERS; } From 67ada816d44f90cb046ea503e0e5071e8fa555e5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 27 Sep 2023 14:59:03 +0000 Subject: [PATCH 37/69] chore(release): 0.118.0-dev.13 [skip ci] # [0.118.0-dev.13](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.12...v0.118.0-dev.13) (2023-09-27) ### Bug Fixes * **YouTube - Client spoof:** fix occasionally frozen video playback ([#486](https://github.com/ReVanced/revanced-integrations/issues/486)) ([b0b6ff6](https://github.com/ReVanced/revanced-integrations/commit/b0b6ff6a82820d4578c5cfc5f69ae7aaaac49c7f)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ded88acdc..f04765b52e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.13](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.12...v0.118.0-dev.13) (2023-09-27) + + +### Bug Fixes + +* **YouTube - Client spoof:** fix occasionally frozen video playback ([#486](https://github.com/ReVanced/revanced-integrations/issues/486)) ([b0b6ff6](https://github.com/ReVanced/revanced-integrations/commit/b0b6ff6a82820d4578c5cfc5f69ae7aaaac49c7f)) + # [0.118.0-dev.12](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.11...v0.118.0-dev.12) (2023-09-26) diff --git a/gradle.properties b/gradle.properties index 036d932c19..80f7fc840d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.12 +version = 0.118.0-dev.13 From a01db14c1e8d9bbebdee98054b5fc248796ac21d Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Wed, 27 Sep 2023 18:02:48 +0200 Subject: [PATCH 38/69] ci: Bump checkout action --- .github/workflows/pull_request.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 2b123ec672..438c1ef850 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Open pull request uses: repo-sync/pull-request@v2 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4fd0e1417..d3ff3d7641 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: # Make sure the release step uses its own credentials: # https://github.com/cycjimmy/semantic-release-action#private-packages From 00c4c4025bc27495e490fdb231ac803881c9887f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 28 Sep 2023 00:18:21 +0400 Subject: [PATCH 39/69] fix(YouTube - Hide info cards): Fix info cards not hiding for some users (#487) --- .../components/HideInfoCardsFilterPatch.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/components/HideInfoCardsFilterPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/components/HideInfoCardsFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/HideInfoCardsFilterPatch.java new file mode 100644 index 0000000000..fc1f9a1e9f --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/components/HideInfoCardsFilterPatch.java @@ -0,0 +1,15 @@ +package app.revanced.integrations.patches.components; + +import app.revanced.integrations.settings.SettingsEnum; + +public final class HideInfoCardsFilterPatch extends Filter { + + public HideInfoCardsFilterPatch() { + identifierFilterGroupList.addAll( + new StringFilterGroup( + SettingsEnum.HIDE_INFO_CARDS, + "info_card_teaser_overlay.eml" + ) + ); + } +} From 1e6fabceeaec80e72719789284ad9d99ae481c6b Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 27 Sep 2023 20:24:38 +0000 Subject: [PATCH 40/69] chore(release): 0.118.0-dev.14 [skip ci] # [0.118.0-dev.14](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.13...v0.118.0-dev.14) (2023-09-27) ### Bug Fixes * **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#487](https://github.com/ReVanced/revanced-integrations/issues/487)) ([00c4c40](https://github.com/ReVanced/revanced-integrations/commit/00c4c4025bc27495e490fdb231ac803881c9887f)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f04765b52e..18eadf74bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.14](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.13...v0.118.0-dev.14) (2023-09-27) + + +### Bug Fixes + +* **YouTube - Hide info cards:** Fix info cards not hiding for some users ([#487](https://github.com/ReVanced/revanced-integrations/issues/487)) ([00c4c40](https://github.com/ReVanced/revanced-integrations/commit/00c4c4025bc27495e490fdb231ac803881c9887f)) + # [0.118.0-dev.13](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.12...v0.118.0-dev.13) (2023-09-27) diff --git a/gradle.properties b/gradle.properties index 80f7fc840d..fdf7207be9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.13 +version = 0.118.0-dev.14 From 5dadb0d523f2b1eb4216d43770af37a156c8a477 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 28 Sep 2023 01:28:34 +0200 Subject: [PATCH 41/69] feat(YouTube): Bump compatibility to `18.37.36` (#483) Co-authored-by: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> --- .../patches/ReturnYouTubeDislikePatch.java | 38 ++++----- .../patches/components/LithoFilterPatch.java | 6 +- .../patches/components/ShortsFilter.java | 82 ++++++++++++++----- .../requests/StoryboardRendererRequester.java | 4 +- .../ReturnYouTubeDislike.java | 2 +- 5 files changed, 86 insertions(+), 46 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index 48a7e81aab..383d3185cb 100644 --- a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -1,25 +1,12 @@ package app.revanced.integrations.patches; -import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; - import android.graphics.Rect; import android.os.Build; -import android.text.Editable; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.TextWatcher; +import android.text.*; import android.view.View; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeApi; import app.revanced.integrations.settings.SettingsEnum; @@ -27,6 +14,13 @@ import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; + /** * Handles all interaction of UI patch components. * @@ -149,23 +143,27 @@ public static CharSequence onLithoTextLoaded(@NonNull Object conversionContext, @NonNull AtomicReference textRef, @NonNull CharSequence original) { try { - if (!SettingsEnum.RYD_ENABLED.getBoolean() || PlayerType.getCurrent().isNoneOrHidden()) { + if (!SettingsEnum.RYD_ENABLED.getBoolean()) { return original; } String conversionContextString = conversionContext.toString(); LogHelper.printDebug(() -> "conversionContext: " + conversionContextString); - final boolean isSegmentedButton; + final Spanned replacement; if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) { - isSegmentedButton = true; - } else if (conversionContextString.contains("|dislike_button.eml|")) { - isSegmentedButton = false; + replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, true); + } else if (conversionContextString.contains("|dislike_button.eml|") ) { + // This code path is basically dead because it's only used when spoofing between 17.09.xx and 17.30.xx + // but spoofing to that range gives a broken UI layout. + // Keep this check here anyways just in case the old litho layout is somehow still used. + replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, false); + } else if (conversionContextString.contains("|shorts_dislike_button.eml|")) { + replacement = ReturnYouTubeDislike.getDislikeSpanForShort((Spannable) original); } else { return original; } - Spanned replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, isSegmentedButton); textRef.set(replacement); return replacement; } catch (Exception ex) { diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index 44cbbeaf10..7cfe060b1d 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -292,10 +292,10 @@ abstract class Filter { boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBufferArray, FilterGroupList matchedList, FilterGroup matchedGroup, int matchedIndex) { if (SettingsEnum.DEBUG.getBoolean()) { - if (pathFilterGroupList == matchedList) { - LogHelper.printDebug(() -> getClass().getSimpleName() + " Filtered path: " + path); - } else if (identifierFilterGroupList == matchedList) { + if (matchedList == identifierFilterGroupList) { LogHelper.printDebug(() -> getClass().getSimpleName() + " Filtered identifier: " + identifier); + } else { + LogHelper.printDebug(() -> getClass().getSimpleName() + " Filtered path: " + path); } } return true; diff --git a/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java index b6e1f3facb..e253d9173f 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java @@ -1,31 +1,29 @@ package app.revanced.integrations.patches.components; -import static app.revanced.integrations.utils.ReVancedUtils.hideViewBy1dpUnderCondition; -import static app.revanced.integrations.utils.ReVancedUtils.hideViewUnderCondition; - +import android.os.Build; import android.view.View; - import androidx.annotation.Nullable; - +import androidx.annotation.RequiresApi; +import app.revanced.integrations.settings.SettingsEnum; import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar; -import app.revanced.integrations.settings.SettingsEnum; +import static app.revanced.integrations.utils.ReVancedUtils.hideViewBy1dpUnderCondition; +import static app.revanced.integrations.utils.ReVancedUtils.hideViewUnderCondition; +@RequiresApi(api = Build.VERSION_CODES.N) public final class ShortsFilter extends Filter { - private static final String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml"; public static PivotBar pivotBar; // Set by patch. + private final String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml"; private final StringFilterGroup channelBar; private final StringFilterGroup soundButton; private final StringFilterGroup infoPanel; - private final StringFilterGroup shortsShelfHeader; + private final StringFilterGroup shelfHeader; + + private final StringFilterGroup videoActionButton; + private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList(); public ShortsFilter() { - // Home / subscription feed components. - var thanksButton = new StringFilterGroup( - SettingsEnum.HIDE_SHORTS_THANKS_BUTTON, - "suggested_action" - ); var shorts = new StringFilterGroup( SettingsEnum.HIDE_SHORTS, "shorts_shelf", @@ -33,14 +31,22 @@ public ShortsFilter() { "shorts_grid", "shorts_video_cell", "shorts_pivot_item" + ); + // Feed Shorts shelf header. // Use a different filter group for this pattern, as it requires an additional check after matching. - shortsShelfHeader = new StringFilterGroup( + shelfHeader = new StringFilterGroup( SettingsEnum.HIDE_SHORTS, "shelf_header.eml" ); - identifierFilterGroupList.addAll(shorts, shortsShelfHeader, thanksButton); + // Home / subscription feed components. + var thanksButton = new StringFilterGroup( + SettingsEnum.HIDE_SHORTS_THANKS_BUTTON, + "suggested_action" + ); + + identifierFilterGroupList.addAll(shorts, shelfHeader, thanksButton); // Shorts player components. var joinButton = new StringFilterGroup( @@ -51,6 +57,7 @@ public ShortsFilter() { SettingsEnum.HIDE_SHORTS_SUBSCRIBE_BUTTON, "subscribe_button" ); + channelBar = new StringFilterGroup( SettingsEnum.HIDE_SHORTS_CHANNEL_BAR, REEL_CHANNEL_BAR_PATH @@ -59,11 +66,37 @@ public ShortsFilter() { SettingsEnum.HIDE_SHORTS_SOUND_BUTTON, "reel_pivot_button" ); + infoPanel = new StringFilterGroup( SettingsEnum.HIDE_SHORTS_INFO_PANEL, "shorts_info_panel_overview" ); - pathFilterGroupList.addAll(joinButton, subscribeButton, channelBar, soundButton, infoPanel); + + videoActionButton = new StringFilterGroup( + null, + "ContainerType|shorts_video_action_button" + ); + + pathFilterGroupList.addAll( + joinButton, subscribeButton, channelBar, soundButton, infoPanel, videoActionButton + ); + + var shortsCommentButton = new ByteArrayAsStringFilterGroup( + SettingsEnum.HIDE_SHORTS_COMMENTS_BUTTON, + "reel_comment_button" + ); + + var shortsShareButton = new ByteArrayAsStringFilterGroup( + SettingsEnum.HIDE_SHORTS_SHARE_BUTTON, + "reel_share_button" + ); + + var shortsRemixButton = new ByteArrayAsStringFilterGroup( + SettingsEnum.HIDE_SHORTS_REMIX_BUTTON, + "reel_remix_button" + ); + + videoActionButtonGroupList.addAll(shortsCommentButton, shortsShareButton, shortsRemixButton); } @Override @@ -72,27 +105,34 @@ boolean isFiltered(@Nullable String identifier, String path, byte[] protobufBuff if (matchedList == pathFilterGroupList) { // Always filter if matched. if (matchedGroup == soundButton || matchedGroup == infoPanel || matchedGroup == channelBar) - return super.isFiltered(path, identifier, protobufBufferArray, matchedList, matchedGroup, matchedIndex); + return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex); + + // Video action buttons (comment, share, remix) have the same path. + if (matchedGroup == videoActionButton) { + if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) + return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex); + return false; + } // Filter other path groups from pathFilterGroupList, only when reelChannelBar is visible // to avoid false positives. if (!path.startsWith(REEL_CHANNEL_BAR_PATH)) return false; - } else if (matchedGroup == shortsShelfHeader) { + } else if (matchedGroup == shelfHeader) { // Because the header is used in watch history and possibly other places, check for the index, // which is 0 when the shelf header is used for Shorts. if (matchedIndex != 0) return false; } // Super class handles logging. - return super.isFiltered(path, identifier, protobufBufferArray, matchedList, matchedGroup, matchedIndex); + return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex); } public static void hideShortsShelf(final View shortsShelfView) { hideViewBy1dpUnderCondition(SettingsEnum.HIDE_SHORTS, shortsShelfView); } - // Additional components that have to be hidden by setting their visibility + // region Hide the buttons in older versions of YouTube. New versions use Litho. public static void hideShortsCommentsButton(final View commentsButtonView) { hideViewUnderCondition(SettingsEnum.HIDE_SHORTS_COMMENTS_BUTTON, commentsButtonView); @@ -106,6 +146,8 @@ public static void hideShortsShareButton(final View shareButtonView) { hideViewUnderCondition(SettingsEnum.HIDE_SHORTS_SHARE_BUTTON, shareButtonView); } + // endregion + public static void hideNavigationBar() { if (!SettingsEnum.HIDE_SHORTS_NAVIGATION_BAR.getBoolean()) return; if (pivotBar == null) return; diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java index d2b79e8dd6..3138630570 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java @@ -100,10 +100,10 @@ public static StoryboardRenderer getStoryboardRenderer(@NonNull String videoId) var renderer = getStoryboardRendererUsingBody(String.format(ANDROID_INNER_TUBE_BODY, videoId)); if (renderer == null) { - LogHelper.printDebug(() -> videoId + " not available using android client"); + LogHelper.printDebug(() -> videoId + " not available using Android client"); renderer = getStoryboardRendererUsingBody(String.format(TV_EMBED_INNER_TUBE_BODY, videoId, videoId)); if (renderer == null) { - LogHelper.printDebug(() -> videoId + " not available using tv embedded client"); + LogHelper.printDebug(() -> videoId + " not available using TV embedded client"); } } diff --git a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java index 7fcd9d0f3b..21f72b9d39 100644 --- a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java @@ -279,7 +279,7 @@ public static Spanned getDislikesSpanForRegularVideo(@NonNull Spanned original, // 2. opened a short (without closing the regular video) // 3. closed the short // 4. regular video is now present, but the videoId and RYD data is still for the short - LogHelper.printDebug(() -> "Ignoring getDislikeSpanForContext(), as data loaded is for prior short"); + LogHelper.printDebug(() -> "Ignoring dislike span, as data loaded is for prior short"); return original; } return waitForFetchAndUpdateReplacementSpan(original, isSegmentedButton); From 444b80026d6b8b2b19bc7a64435049cc5cdc77b4 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Wed, 27 Sep 2023 23:32:17 +0000 Subject: [PATCH 42/69] chore(release): 0.118.0-dev.15 [skip ci] # [0.118.0-dev.15](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.14...v0.118.0-dev.15) (2023-09-27) ### Features * **YouTube:** Bump compatibility to `18.37.36` ([#483](https://github.com/ReVanced/revanced-integrations/issues/483)) ([5dadb0d](https://github.com/ReVanced/revanced-integrations/commit/5dadb0d523f2b1eb4216d43770af37a156c8a477)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18eadf74bc..47ed42feac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.15](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.14...v0.118.0-dev.15) (2023-09-27) + + +### Features + +* **YouTube:** Bump compatibility to `18.37.36` ([#483](https://github.com/ReVanced/revanced-integrations/issues/483)) ([5dadb0d](https://github.com/ReVanced/revanced-integrations/commit/5dadb0d523f2b1eb4216d43770af37a156c8a477)) + # [0.118.0-dev.14](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.13...v0.118.0-dev.14) (2023-09-27) diff --git a/gradle.properties b/gradle.properties index fdf7207be9..9c8631bf72 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.14 +version = 0.118.0-dev.15 From 91096532eedf396920d69932638f667cbf850cbe Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Thu, 28 Sep 2023 04:47:40 +0200 Subject: [PATCH 43/69] feat(YouTube): Add `Bypass URL redirects` patch --- .../patches/BypassURLRedirectsPatch.java | 29 +++++++++++++++++++ .../integrations/settings/SettingsEnum.java | 1 + 2 files changed, 30 insertions(+) create mode 100644 app/src/main/java/app/revanced/integrations/patches/BypassURLRedirectsPatch.java diff --git a/app/src/main/java/app/revanced/integrations/patches/BypassURLRedirectsPatch.java b/app/src/main/java/app/revanced/integrations/patches/BypassURLRedirectsPatch.java new file mode 100644 index 0000000000..dd062e0372 --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/BypassURLRedirectsPatch.java @@ -0,0 +1,29 @@ +package app.revanced.integrations.patches; + +import android.net.Uri; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; + +public class BypassURLRedirectsPatch { + private static final String YOUTUBE_REDIRECT_PATH = "/redirect"; + + /** + * Convert the YouTube redirect URI string to the redirect query URI. + * + * @param uri The YouTube redirect URI string. + * @return The redirect query URI. + */ + public static Uri parseRedirectUri(String uri) { + final var parsed = Uri.parse(uri); + + if (SettingsEnum.BYPASS_URL_REDIRECTS.getBoolean() && parsed.getPath().equals(YOUTUBE_REDIRECT_PATH)) { + var query = Uri.parse(Uri.decode(parsed.getQueryParameter("q"))); + + LogHelper.printDebug(() -> "Bypassing YouTube redirect URI: " + query); + + return query; + } + + return parsed; + } +} diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 3ab42ddd6d..699abe4d75 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -169,6 +169,7 @@ public enum SettingsEnum { "revanced_spoof_signature_verification_enabled_user_dialog_message"), SPOOF_SIGNATURE_IN_FEED("revanced_spoof_signature_in_feed_enabled", BOOLEAN, FALSE, false, parents(SPOOF_SIGNATURE)), + BYPASS_URL_REDIRECTS("revanced_bypass_url_redirects", BOOLEAN, TRUE), // Swipe controls SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE), From cc416bc4f6e50eb75c8eea34f307dfd90b844c8e Mon Sep 17 00:00:00 2001 From: nullptr <107796137+johnconner122@users.noreply.github.com> Date: Thu, 28 Sep 2023 07:49:12 +0500 Subject: [PATCH 44/69] chore: Log hiding mix playlists (#485) Co-authored-by: oSumAtrIX --- .../patches/components/LayoutComponentsFilter.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 8e88200a2e..f3057933af 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -195,6 +195,11 @@ public boolean isFiltered(@Nullable String identifier, String path, byte[] proto * Called from a different place then the other filters. */ public static boolean filterMixPlaylists(final byte[] bytes) { - return mixPlaylists.check(bytes).isFiltered(); + final boolean isMixPlaylistFiltered = mixPlaylists.check(bytes).isFiltered(); + + if (isMixPlaylistFiltered) + LogHelper.printDebug(() -> "Filtered mix playlist"); + + return isMixPlaylistFiltered; } } From e7e02e1e30991b292a5af17be231a06ca1c1638f Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 28 Sep 2023 11:48:27 +0400 Subject: [PATCH 45/69] chore: fix build --- .../integrations/patches/components/LayoutComponentsFilter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index f3057933af..7c227ba78c 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -7,6 +7,7 @@ import androidx.annotation.RequiresApi; import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.StringTrieSearch; @RequiresApi(api = Build.VERSION_CODES.N) From 4b256f501b9123606c9b2e3386071b03b1e2f945 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 28 Sep 2023 07:52:02 +0000 Subject: [PATCH 46/69] chore(release): 0.118.0-dev.16 [skip ci] # [0.118.0-dev.16](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.15...v0.118.0-dev.16) (2023-09-28) ### Features * **YouTube:** Add `Bypass URL redirects` patch ([9109653](https://github.com/ReVanced/revanced-integrations/commit/91096532eedf396920d69932638f667cbf850cbe)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47ed42feac..ea31817b81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.16](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.15...v0.118.0-dev.16) (2023-09-28) + + +### Features + +* **YouTube:** Add `Bypass URL redirects` patch ([9109653](https://github.com/ReVanced/revanced-integrations/commit/91096532eedf396920d69932638f667cbf850cbe)) + # [0.118.0-dev.15](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.14...v0.118.0-dev.15) (2023-09-27) diff --git a/gradle.properties b/gradle.properties index 9c8631bf72..507cb29c63 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.15 +version = 0.118.0-dev.16 From da923a38a06baf8c30d38211e8354be4edb0ad51 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:11:54 +0400 Subject: [PATCH 47/69] fix(YouTube - Video Id): Fix video id not showing the currently playing video (#484) Co-authored-by: oSumAtrIX --- .../patches/VideoInformation.java | 41 ++++++++++++++++--- .../patches/spoof/SpoofSignaturePatch.java | 35 +++++++++------- 2 files changed, 56 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java b/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java index ad5bcd1686..ee9034b0b3 100644 --- a/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java +++ b/app/src/main/java/app/revanced/integrations/patches/VideoInformation.java @@ -1,16 +1,15 @@ package app.revanced.integrations.patches; import androidx.annotation.NonNull; - -import java.lang.ref.WeakReference; -import java.lang.reflect.Method; -import java.util.Objects; - import app.revanced.integrations.patches.playback.speed.RememberPlaybackSpeedPatch; import app.revanced.integrations.shared.VideoState; import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; +import java.util.Objects; + /** * Hooking class for the current playing video. */ @@ -25,6 +24,10 @@ public final class VideoInformation { private static String videoId = ""; private static long videoLength = 0; private static long videoTime = -1; + + @NonNull + private static volatile String playerResponseVideoId = ""; + /** * The current playback speed */ @@ -61,6 +64,18 @@ public static void setVideoId(@NonNull String newlyLoadedVideoId) { } } + /** + * Injection point. Called off the main thread. + * + * @param videoId The id of the last video loaded. + */ + public static void setPlayerResponseVideoId(@NonNull String videoId) { + if (!playerResponseVideoId.equals(videoId)) { + LogHelper.printDebug(() -> "New player response video id: " + videoId); + playerResponseVideoId = videoId; + } + } + /** * Injection point. * Called when user selects a playback speed. @@ -141,6 +156,22 @@ public static String getVideoId() { return videoId; } + /** + * Differs from {@link #videoId} as this is the video id for the + * last player response received, which may not be the current video playing. + * + * If Shorts are loading the background, this commonly will be + * different from the Short that is currently on screen. + * + * For most use cases, you should instead use {@link #getVideoId()}. + * + * @return The id of the last video loaded. Empty string if not set yet. + */ + @NonNull + public static String getPlayerResponseVideoId() { + return playerResponseVideoId; + } + /** * @return The current playback speed. */ diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 69f00abfd6..42392480ad 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -1,19 +1,20 @@ package app.revanced.integrations.patches.spoof; +import static app.revanced.integrations.patches.spoof.requests.StoryboardRendererRequester.getStoryboardRenderer; +import static app.revanced.integrations.utils.ReVancedUtils.containsAny; + import androidx.annotation.Nullable; -import app.revanced.integrations.patches.VideoInformation; -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.shared.PlayerType; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static app.revanced.integrations.patches.spoof.requests.StoryboardRendererRequester.getStoryboardRenderer; -import static app.revanced.integrations.utils.ReVancedUtils.containsAny; +import app.revanced.integrations.patches.VideoInformation; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.shared.PlayerType; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; /** @noinspection unused*/ public class SpoofSignaturePatch { @@ -46,7 +47,7 @@ public class SpoofSignaturePatch { /** * Last video id loaded. Used to prevent reloading the same spec multiple times. */ - private static volatile String currentVideoId; + private static volatile String lastPlayerResponseVideoId; private static volatile Future rendererFuture; @@ -83,7 +84,6 @@ public static String spoofParameter(String parameters) { var isClip = parameters.length() > 150; if (isClip) return parameters; - // Shorts do not need to be spoofed. if (parameters.startsWith(SHORTS_PLAYER_PARAMETERS)) return parameters; @@ -96,18 +96,23 @@ public static String spoofParameter(String parameters) { // This will cause playback issues in the feed, but it's better than manipulating the history. parameters; - String videoId = VideoInformation.getVideoId(); - if (!videoId.equals(currentVideoId)) { + fetchStoryboardRenderer(); + + return INCOGNITO_PARAMETERS; + } + + private static void fetchStoryboardRenderer() { + String videoId = VideoInformation.getPlayerResponseVideoId(); + if (!videoId.equals(lastPlayerResponseVideoId)) { rendererFuture = ReVancedUtils.submitOnBackgroundThread(() -> getStoryboardRenderer(videoId)); - currentVideoId = videoId; + lastPlayerResponseVideoId = videoId; } - // Occasionally when a new video is opened the video will be frozen a few seconds while the audio plays. + // Block until the fetch is completed. Without this, occasionally when a new video is opened + // the video will be frozen a few seconds while the audio plays. // This is because the main thread is calling to get the storyboard but the fetch is not completed. // To prevent this, call get() here and block until the fetch is completed. // So later when the main thread calls to get the renderer it will never block as the future is done. getRenderer(); - - return INCOGNITO_PARAMETERS; } /** From 27f49dfd1e8fbfd3e28270da91ad437df8a54761 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:12:14 +0400 Subject: [PATCH 48/69] fix(YouTube - Client spoof): Fix toast shown for live streams (#489) --- .../patches/spoof/SpoofSignaturePatch.java | 23 +++++++++++-------- .../patches/spoof/StoryboardRenderer.java | 13 ++++++++--- .../requests/StoryboardRendererRequester.java | 6 +++-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java index 42392480ad..16a284d049 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofSignaturePatch.java @@ -128,23 +128,26 @@ public static boolean getSeekbarThumbnailOverrideValue() { */ @Nullable public static String getStoryboardRendererSpec(String originalStoryboardRendererSpec) { - if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalStoryboardRendererSpec; - - StoryboardRenderer renderer = getRenderer(); - if (renderer == null) return originalStoryboardRendererSpec; + if (SettingsEnum.SPOOF_SIGNATURE.getBoolean()) { + StoryboardRenderer renderer = getRenderer(); + if (renderer != null) return renderer.getSpec(); + } - return renderer.getSpec(); + return originalStoryboardRendererSpec; } /** * Injection point. */ public static int getRecommendedLevel(int originalLevel) { - if (!SettingsEnum.SPOOF_SIGNATURE.getBoolean()) return originalLevel; - - StoryboardRenderer renderer = getRenderer(); - if (renderer == null) return originalLevel; + if (SettingsEnum.SPOOF_SIGNATURE.getBoolean()) { + StoryboardRenderer renderer = getRenderer(); + if (renderer != null) { + Integer recommendedLevel = renderer.getRecommendedLevel(); + if (recommendedLevel != null) return recommendedLevel; + } + } - return renderer.getRecommendedLevel(); + return originalLevel; } } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java b/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java index c7ce43e57d..d0e70988bf 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/StoryboardRenderer.java @@ -1,13 +1,16 @@ package app.revanced.integrations.patches.spoof; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import org.jetbrains.annotations.NotNull; public final class StoryboardRenderer { private final String spec; - private final int recommendedLevel; + @Nullable + private final Integer recommendedLevel; - public StoryboardRenderer(String spec, int recommendedLevel) { + public StoryboardRenderer(String spec, @Nullable Integer recommendedLevel) { this.spec = spec; this.recommendedLevel = recommendedLevel; } @@ -17,7 +20,11 @@ public String getSpec() { return spec; } - public int getRecommendedLevel() { + /** + * @return Recommended image quality level, or NULL if no recommendation exists. + */ + @Nullable + public Integer getRecommendedLevel() { return recommendedLevel; } diff --git a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java index 3138630570..61828a04bb 100644 --- a/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/requests/StoryboardRendererRequester.java @@ -49,7 +49,7 @@ private static boolean isPlayabilityStatusOk(@NonNull JSONObject playerResponse) try { return playerResponse.getJSONObject("playabilityStatus").getString("status").equals("OK"); } catch (JSONException e) { - LogHelper.printException(() -> "Failed to get playabilityStatus", e); + LogHelper.printDebug(() -> "Failed to get playabilityStatus for response: " + playerResponse); } return false; @@ -80,7 +80,9 @@ private static StoryboardRenderer getStoryboardRendererUsingResponse(@NonNull JS final var rendererElement = storyboards.getJSONObject(storyboardsRendererTag); StoryboardRenderer renderer = new StoryboardRenderer( rendererElement.getString("spec"), - rendererElement.getInt("recommendedLevel") + rendererElement.has("recommendedLevel") + ? rendererElement.getInt("recommendedLevel") + : null ); LogHelper.printDebug(() -> "Fetched: " + renderer); From 78bea48e4045602e6cdabfac31cd46c3e785e810 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 28 Sep 2023 13:16:02 +0000 Subject: [PATCH 49/69] chore(release): 0.118.0-dev.17 [skip ci] # [0.118.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.16...v0.118.0-dev.17) (2023-09-28) ### Bug Fixes * **YouTube - Client spoof:** Fix toast shown for live streams ([#489](https://github.com/ReVanced/revanced-integrations/issues/489)) ([27f49df](https://github.com/ReVanced/revanced-integrations/commit/27f49dfd1e8fbfd3e28270da91ad437df8a54761)) * **YouTube - Video Id:** Fix video id not showing the currently playing video ([#484](https://github.com/ReVanced/revanced-integrations/issues/484)) ([da923a3](https://github.com/ReVanced/revanced-integrations/commit/da923a38a06baf8c30d38211e8354be4edb0ad51)) --- CHANGELOG.md | 8 ++++++++ gradle.properties | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea31817b81..377555f42b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [0.118.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.16...v0.118.0-dev.17) (2023-09-28) + + +### Bug Fixes + +* **YouTube - Client spoof:** Fix toast shown for live streams ([#489](https://github.com/ReVanced/revanced-integrations/issues/489)) ([27f49df](https://github.com/ReVanced/revanced-integrations/commit/27f49dfd1e8fbfd3e28270da91ad437df8a54761)) +* **YouTube - Video Id:** Fix video id not showing the currently playing video ([#484](https://github.com/ReVanced/revanced-integrations/issues/484)) ([da923a3](https://github.com/ReVanced/revanced-integrations/commit/da923a38a06baf8c30d38211e8354be4edb0ad51)) + # [0.118.0-dev.16](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.15...v0.118.0-dev.16) (2023-09-28) diff --git a/gradle.properties b/gradle.properties index 507cb29c63..af8668ee1b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.16 +version = 0.118.0-dev.17 From 165b061fa9c5fd48b0dbb9540fd6ea6a9ffaf312 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:39:11 +0400 Subject: [PATCH 50/69] fix(YouTube - ReturnYouTubeDislike): Revert support for 18.37.36 (#488) --- .../patches/ReturnYouTubeDislikePatch.java | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index 383d3185cb..48a7e81aab 100644 --- a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -1,25 +1,31 @@ package app.revanced.integrations.patches; +import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; + import android.graphics.Rect; import android.os.Build; -import android.text.*; +import android.text.Editable; +import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; +import android.text.TextWatcher; import android.view.View; import android.widget.TextView; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; -import app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeApi; -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.shared.PlayerType; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; +import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; +import app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeApi; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.shared.PlayerType; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; /** * Handles all interaction of UI patch components. @@ -143,27 +149,23 @@ public static CharSequence onLithoTextLoaded(@NonNull Object conversionContext, @NonNull AtomicReference textRef, @NonNull CharSequence original) { try { - if (!SettingsEnum.RYD_ENABLED.getBoolean()) { + if (!SettingsEnum.RYD_ENABLED.getBoolean() || PlayerType.getCurrent().isNoneOrHidden()) { return original; } String conversionContextString = conversionContext.toString(); LogHelper.printDebug(() -> "conversionContext: " + conversionContextString); - final Spanned replacement; + final boolean isSegmentedButton; if (conversionContextString.contains("|segmented_like_dislike_button.eml|")) { - replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, true); - } else if (conversionContextString.contains("|dislike_button.eml|") ) { - // This code path is basically dead because it's only used when spoofing between 17.09.xx and 17.30.xx - // but spoofing to that range gives a broken UI layout. - // Keep this check here anyways just in case the old litho layout is somehow still used. - replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, false); - } else if (conversionContextString.contains("|shorts_dislike_button.eml|")) { - replacement = ReturnYouTubeDislike.getDislikeSpanForShort((Spannable) original); + isSegmentedButton = true; + } else if (conversionContextString.contains("|dislike_button.eml|")) { + isSegmentedButton = false; } else { return original; } + Spanned replacement = ReturnYouTubeDislike.getDislikesSpanForRegularVideo((Spannable) original, isSegmentedButton); textRef.set(replacement); return replacement; } catch (Exception ex) { From 7dfa0e465344b554b7f88a26f363206467ab9cf5 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Thu, 28 Sep 2023 13:42:52 +0000 Subject: [PATCH 51/69] chore(release): 0.118.0-dev.18 [skip ci] # [0.118.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.17...v0.118.0-dev.18) (2023-09-28) ### Bug Fixes * **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#488](https://github.com/ReVanced/revanced-integrations/issues/488)) ([165b061](https://github.com/ReVanced/revanced-integrations/commit/165b061fa9c5fd48b0dbb9540fd6ea6a9ffaf312)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 377555f42b..562c8a234b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.17...v0.118.0-dev.18) (2023-09-28) + + +### Bug Fixes + +* **YouTube - ReturnYouTubeDislike:** Revert support for 18.37.36 ([#488](https://github.com/ReVanced/revanced-integrations/issues/488)) ([165b061](https://github.com/ReVanced/revanced-integrations/commit/165b061fa9c5fd48b0dbb9540fd6ea6a9ffaf312)) + # [0.118.0-dev.17](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.16...v0.118.0-dev.17) (2023-09-28) diff --git a/gradle.properties b/gradle.properties index af8668ee1b..def176f774 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.17 +version = 0.118.0-dev.18 From b472aeeed7904f6b6d537dfbddda1a97c7ddcd5e Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 1 Oct 2023 05:02:35 +0200 Subject: [PATCH 52/69] feat(YouTube - Hide layout components): Hide timed reactions --- .../patches/components/LayoutComponentsFilter.java | 7 +++++++ .../app/revanced/integrations/settings/SettingsEnum.java | 1 + 2 files changed, 8 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 7c227ba78c..acc322ae55 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -146,6 +146,12 @@ public LayoutComponentsFilter() { "cell_divider" // layout residue (gray line above the buttoned ad), ); + final var timedReactions = new StringFilterGroup( + SettingsEnum.HIDE_TIMED_REACTIONS, + "emoji_control_panel", + "timed_reaction" + ); + final var chipsShelf = new StringFilterGroup( SettingsEnum.HIDE_CHIPS_SHELF, "chips_shelf" @@ -168,6 +174,7 @@ public LayoutComponentsFilter() { channelGuidelines, audioTrackButton, artistCard, + timedReactions, imageShelf, subscribersCommunityGuidelines, channelMemberShelf, diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 699abe4d75..35a5703272 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -65,6 +65,7 @@ public enum SettingsEnum { HIDE_EMERGENCY_BOX("revanced_hide_emergency_box", BOOLEAN, TRUE), HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE), HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE), + HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE), HIDE_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE), HIDE_HIDE_INFO_PANELS("revanced_hide_info_panels", BOOLEAN, TRUE), From b87d8066597a2c989480de47561007844964a0e4 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 1 Oct 2023 05:04:43 +0200 Subject: [PATCH 53/69] feat(YouTube - Hide layout components): Hide "Notify me" button --- .../patches/components/LayoutComponentsFilter.java | 6 ++++++ .../app/revanced/integrations/settings/SettingsEnum.java | 2 ++ 2 files changed, 8 insertions(+) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index acc322ae55..087855d0a2 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -152,6 +152,11 @@ public LayoutComponentsFilter() { "timed_reaction" ); + final var notifyMe = new StringFilterGroup( + SettingsEnum.HIDE_NOTIFY_ME_BUTTON, + "set_reminder_button" + ); + final var chipsShelf = new StringFilterGroup( SettingsEnum.HIDE_CHIPS_SHELF, "chips_shelf" @@ -170,6 +175,7 @@ public LayoutComponentsFilter() { compactBanner, inFeedSurvey, medicalPanel, + notifyMe, infoPanel, channelGuidelines, audioTrackButton, diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 35a5703272..30a852bd85 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -66,6 +66,8 @@ public enum SettingsEnum { HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE), HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE), HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), + HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE), + HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE), HIDE_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE), HIDE_HIDE_INFO_PANELS("revanced_hide_info_panels", BOOLEAN, TRUE), From e2254681cd77481376e4c3f8c556db510fdfce6c Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Sun, 1 Oct 2023 05:07:29 +0200 Subject: [PATCH 54/69] feat(YouTube - Hide layout components): Hide "Join" button --- .../patches/components/LayoutComponentsFilter.java | 6 ++++++ .../app/revanced/integrations/settings/SettingsEnum.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 087855d0a2..83291f6991 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -157,6 +157,11 @@ public LayoutComponentsFilter() { "set_reminder_button" ); + final var joinMembership = new StringFilterGroup( + SettingsEnum.HIDE_JOIN_MEMBERSHIP_BUTTON, + "compact_sponsor_button" + ); + final var chipsShelf = new StringFilterGroup( SettingsEnum.HIDE_CHIPS_SHELF, "chips_shelf" @@ -174,6 +179,7 @@ public LayoutComponentsFilter() { relatedVideos, compactBanner, inFeedSurvey, + joinMembership, medicalPanel, notifyMe, infoPanel, diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 30a852bd85..4a6e895389 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -67,7 +67,7 @@ public enum SettingsEnum { HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE), HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE), - + HIDE_JOIN_MEMBERSHIP_BUTTON("revanced_hide_join_membership_button", BOOLEAN, TRUE), HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE), HIDE_IMAGE_SHELF("revanced_hide_image_shelf", BOOLEAN, TRUE), HIDE_HIDE_INFO_PANELS("revanced_hide_info_panels", BOOLEAN, TRUE), From c992289d59fba5c9439bcec5d37aabb2730a0e61 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 1 Oct 2023 03:11:33 +0000 Subject: [PATCH 55/69] chore(release): 0.118.0-dev.19 [skip ci] # [0.118.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.18...v0.118.0-dev.19) (2023-10-01) ### Features * **YouTube - Hide layout components:** Hide "Join" button ([e225468](https://github.com/ReVanced/revanced-integrations/commit/e2254681cd77481376e4c3f8c556db510fdfce6c)) * **YouTube - Hide layout components:** Hide "Notify me" button ([b87d806](https://github.com/ReVanced/revanced-integrations/commit/b87d8066597a2c989480de47561007844964a0e4)) * **YouTube - Hide layout components:** Hide timed reactions ([b472aee](https://github.com/ReVanced/revanced-integrations/commit/b472aeeed7904f6b6d537dfbddda1a97c7ddcd5e)) --- CHANGELOG.md | 9 +++++++++ gradle.properties | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 562c8a234b..94966e1eaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# [0.118.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.18...v0.118.0-dev.19) (2023-10-01) + + +### Features + +* **YouTube - Hide layout components:** Hide "Join" button ([e225468](https://github.com/ReVanced/revanced-integrations/commit/e2254681cd77481376e4c3f8c556db510fdfce6c)) +* **YouTube - Hide layout components:** Hide "Notify me" button ([b87d806](https://github.com/ReVanced/revanced-integrations/commit/b87d8066597a2c989480de47561007844964a0e4)) +* **YouTube - Hide layout components:** Hide timed reactions ([b472aee](https://github.com/ReVanced/revanced-integrations/commit/b472aeeed7904f6b6d537dfbddda1a97c7ddcd5e)) + # [0.118.0-dev.18](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.17...v0.118.0-dev.18) (2023-09-28) diff --git a/gradle.properties b/gradle.properties index def176f774..b067ac1d36 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.18 +version = 0.118.0-dev.19 From 1689bf412593558244587ffaf291fb9587f27103 Mon Sep 17 00:00:00 2001 From: Temm Date: Sun, 1 Oct 2023 05:12:00 +0200 Subject: [PATCH 56/69] refactor(Tumblr): Use a common filter patch (#479) Co-authored-by: oSumAtrIX --- .../tumblr/patches/TimelineFilterPatch.java | 32 +++++++++++++++++++ .../tumblr/rumblr/model/TimelineObject.java | 8 +++++ .../rumblr/model/TimelineObjectType.java | 4 +++ .../com/tumblr/rumblr/model/Timelineable.java | 5 +++ 4 files changed, 49 insertions(+) create mode 100644 app/src/main/java/app/revanced/tumblr/patches/TimelineFilterPatch.java create mode 100644 dummy/src/main/java/com/tumblr/rumblr/model/TimelineObject.java create mode 100644 dummy/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java create mode 100644 dummy/src/main/java/com/tumblr/rumblr/model/Timelineable.java diff --git a/app/src/main/java/app/revanced/tumblr/patches/TimelineFilterPatch.java b/app/src/main/java/app/revanced/tumblr/patches/TimelineFilterPatch.java new file mode 100644 index 0000000000..1a4d50eff3 --- /dev/null +++ b/app/src/main/java/app/revanced/tumblr/patches/TimelineFilterPatch.java @@ -0,0 +1,32 @@ +package app.revanced.tumblr.patches; + +import com.tumblr.rumblr.model.TimelineObject; +import com.tumblr.rumblr.model.Timelineable; + +import java.util.HashSet; +import java.util.List; + +public final class TimelineFilterPatch { + private static final HashSet blockedObjectTypes = new HashSet<>(); + + static { + // This dummy gets removed by the TimelineFilterPatch and in its place, + // equivalent instructions with a different constant string + // will be inserted for each Timeline object type filter. + // Modifying this line may break the patch. + blockedObjectTypes.add("BLOCKED_OBJECT_DUMMY"); + } + + // Calls to this method are injected where the list of Timeline objects is first received. + // We modify the list filter out elements that we want to hide. + public static void filterTimeline(final List> timelineObjects) { + final var iterator = timelineObjects.iterator(); + while (iterator.hasNext()) { + var timelineElement = iterator.next(); + if (timelineElement == null) continue; + + String elementType = timelineElement.getData().getTimelineObjectType().toString(); + if (blockedObjectTypes.contains(elementType)) iterator.remove(); + } + } +} diff --git a/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObject.java b/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObject.java new file mode 100644 index 0000000000..8bb2c885d4 --- /dev/null +++ b/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObject.java @@ -0,0 +1,8 @@ +package com.tumblr.rumblr.model; + +public class TimelineObject { + public final T getData() { + throw new UnsupportedOperationException("Stub"); + } + +} diff --git a/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java b/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java new file mode 100644 index 0000000000..f9b7d7abca --- /dev/null +++ b/dummy/src/main/java/com/tumblr/rumblr/model/TimelineObjectType.java @@ -0,0 +1,4 @@ +package com.tumblr.rumblr.model; + +public enum TimelineObjectType { +} diff --git a/dummy/src/main/java/com/tumblr/rumblr/model/Timelineable.java b/dummy/src/main/java/com/tumblr/rumblr/model/Timelineable.java new file mode 100644 index 0000000000..bf84887def --- /dev/null +++ b/dummy/src/main/java/com/tumblr/rumblr/model/Timelineable.java @@ -0,0 +1,5 @@ +package com.tumblr.rumblr.model; + +public interface Timelineable { + TimelineObjectType getTimelineObjectType(); +} From 9685070eda5b448eb33324b4bfabd4c7eae42f9f Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 2 Oct 2023 00:50:18 +0200 Subject: [PATCH 57/69] fix(YouTube - Hide shorts components): Hide subscribe button in paused state --- .../revanced/integrations/patches/components/ShortsFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java index e253d9173f..6b03173b07 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/ShortsFilter.java @@ -55,7 +55,8 @@ public ShortsFilter() { ); var subscribeButton = new StringFilterGroup( SettingsEnum.HIDE_SHORTS_SUBSCRIBE_BUTTON, - "subscribe_button" + "subscribe_button", + "shorts_paused_state" ); channelBar = new StringFilterGroup( From d156951460f9521842302c849a8d31af20670f01 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Sun, 1 Oct 2023 22:54:38 +0000 Subject: [PATCH 58/69] chore(release): 0.118.0-dev.20 [skip ci] # [0.118.0-dev.20](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.19...v0.118.0-dev.20) (2023-10-01) ### Bug Fixes * **YouTube - Hide shorts components:** Hide subscribe button in paused state ([9685070](https://github.com/ReVanced/revanced-integrations/commit/9685070eda5b448eb33324b4bfabd4c7eae42f9f)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94966e1eaa..aed0936615 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.20](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.19...v0.118.0-dev.20) (2023-10-01) + + +### Bug Fixes + +* **YouTube - Hide shorts components:** Hide subscribe button in paused state ([9685070](https://github.com/ReVanced/revanced-integrations/commit/9685070eda5b448eb33324b4bfabd4c7eae42f9f)) + # [0.118.0-dev.19](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.18...v0.118.0-dev.19) (2023-10-01) diff --git a/gradle.properties b/gradle.properties index b067ac1d36..a218275c56 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.19 +version = 0.118.0-dev.20 From 93a30453d9693e015b1f58a12f85cf355770a4ca Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 2 Oct 2023 01:12:59 +0200 Subject: [PATCH 59/69] feat(YouTube - Hide layout components): Hide search result shelf header --- .../components/LayoutComponentsFilter.java | 8 ++++++- .../patches/components/LithoFilterPatch.java | 12 ++++++++++ .../integrations/settings/SettingsEnum.java | 1 + .../integrations/utils/ReVancedUtils.java | 22 ++++++++----------- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index 83291f6991..d03ccbb015 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -152,6 +152,11 @@ public LayoutComponentsFilter() { "timed_reaction" ); + final var searchResultShelfHeader = new StartsWithStringFilterGroup( + SettingsEnum.HIDE_SEARCH_RESULT_SHELF_HEADER, + "shelf_header.eml" + ); + final var notifyMe = new StringFilterGroup( SettingsEnum.HIDE_NOTIFY_ME_BUTTON, "set_reminder_button" @@ -183,12 +188,13 @@ public LayoutComponentsFilter() { medicalPanel, notifyMe, infoPanel, + subscribersCommunityGuidelines, channelGuidelines, audioTrackButton, artistCard, timedReactions, imageShelf, - subscribersCommunityGuidelines, + searchResultShelfHeader, channelMemberShelf, custom ); diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index 7cfe060b1d..da030a3725 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -85,6 +85,18 @@ public FilterGroupResult check(final String string) { } } +class StartsWithStringFilterGroup extends StringFilterGroup { + + public StartsWithStringFilterGroup(final SettingsEnum setting, final String... filters) { + super(setting, filters); + } + + @Override + public FilterGroupResult check(final String string) { + return new FilterGroupResult(setting, isEnabled() && ReVancedUtils.startsWithAny(string, filters)); + } +} + final class CustomFilterGroup extends StringFilterGroup { public CustomFilterGroup(final SettingsEnum setting, final SettingsEnum filter) { diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 4a6e895389..5e5c56ffd1 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -66,6 +66,7 @@ public enum SettingsEnum { HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE), HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE), HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), + HIDE_SEARCH_RESULT_SHELF_HEADER("revanced_hide_search_result_shelf_header", BOOLEAN, TRUE), HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE), HIDE_JOIN_MEMBERSHIP_BUTTON("revanced_hide_join_membership_button", BOOLEAN, TRUE), HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE), diff --git a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java index 564de2c384..a145bbfc75 100644 --- a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java +++ b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java @@ -10,25 +10,15 @@ import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.Toast; -import android.widget.Toolbar; - +import android.widget.*; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import app.revanced.integrations.settings.SettingsEnum; import java.text.Bidi; import java.util.Locale; import java.util.Objects; -import java.util.concurrent.Callable; -import java.util.concurrent.Future; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import app.revanced.integrations.settings.SettingsEnum; +import java.util.concurrent.*; public class ReVancedUtils { @@ -98,6 +88,12 @@ public static boolean containsAny(@NonNull String value, @NonNull String... targ return false; } + public static boolean startsWithAny(@NonNull String value, @NonNull String... targets) { + for (String string : targets) + if (!string.isEmpty() && value.startsWith(string)) return true; + return false; + } + /** * @return zero, if the resource is not found */ From 5185673780252f14f97d18c56ef25648a71a5b5e Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 2 Oct 2023 15:26:40 +0200 Subject: [PATCH 60/69] refactor: Move classes to correct path --- .../patches/ReturnYouTubeDislikePatch.java | 23 ++++++++----------- .../{ => spoof}/SpoofAppVersionPatch.java | 2 +- 2 files changed, 10 insertions(+), 15 deletions(-) rename app/src/main/java/app/revanced/integrations/patches/{ => spoof}/SpoofAppVersionPatch.java (87%) diff --git a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java index 48a7e81aab..2c3b3d0fe1 100644 --- a/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/ReturnYouTubeDislikePatch.java @@ -1,25 +1,13 @@ package app.revanced.integrations.patches; -import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; - import android.graphics.Rect; import android.os.Build; -import android.text.Editable; -import android.text.Spannable; -import android.text.SpannableString; -import android.text.Spanned; -import android.text.TextWatcher; +import android.text.*; import android.view.View; import android.widget.TextView; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - +import app.revanced.integrations.patches.spoof.SpoofAppVersionPatch; import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike; import app.revanced.integrations.returnyoutubedislike.requests.ReturnYouTubeDislikeApi; import app.revanced.integrations.settings.SettingsEnum; @@ -27,6 +15,13 @@ import app.revanced.integrations.utils.LogHelper; import app.revanced.integrations.utils.ReVancedUtils; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote; + /** * Handles all interaction of UI patch components. * diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofAppVersionPatch.java b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java similarity index 87% rename from app/src/main/java/app/revanced/integrations/patches/SpoofAppVersionPatch.java rename to app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java index 4967bb9519..c43d603127 100644 --- a/app/src/main/java/app/revanced/integrations/patches/SpoofAppVersionPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/spoof/SpoofAppVersionPatch.java @@ -1,4 +1,4 @@ -package app.revanced.integrations.patches; +package app.revanced.integrations.patches.spoof; import app.revanced.integrations.settings.SettingsEnum; From f451d67dcb14fd5cd5d2e8ae736372ca3046fdcd Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 2 Oct 2023 14:29:22 +0000 Subject: [PATCH 61/69] chore(release): 0.118.0-dev.21 [skip ci] # [0.118.0-dev.21](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.20...v0.118.0-dev.21) (2023-10-02) ### Features * **YouTube - Hide layout components:** Hide search result shelf header ([93a3045](https://github.com/ReVanced/revanced-integrations/commit/93a30453d9693e015b1f58a12f85cf355770a4ca)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aed0936615..a84b385311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.21](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.20...v0.118.0-dev.21) (2023-10-02) + + +### Features + +* **YouTube - Hide layout components:** Hide search result shelf header ([93a3045](https://github.com/ReVanced/revanced-integrations/commit/93a30453d9693e015b1f58a12f85cf355770a4ca)) + # [0.118.0-dev.20](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.19...v0.118.0-dev.20) (2023-10-01) diff --git a/gradle.properties b/gradle.properties index a218275c56..4831a7515d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.20 +version = 0.118.0-dev.21 From 25f73eb3a93699301d1211c306b7f4a896377b5e Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 2 Oct 2023 22:05:31 +0200 Subject: [PATCH 62/69] refactor: Simplify filtering a component --- .../patches/components/LayoutComponentsFilter.java | 6 ++++-- .../patches/components/LithoFilterPatch.java | 12 ------------ .../revanced/integrations/utils/ReVancedUtils.java | 6 ------ 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index d03ccbb015..e197d4c8a2 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -19,6 +19,7 @@ public final class LayoutComponentsFilter extends Filter { SettingsEnum.HIDE_MIX_PLAYLISTS, "&list=" ); + private final StringFilterGroup searchResultShelfHeader; @RequiresApi(api = Build.VERSION_CODES.N) public LayoutComponentsFilter() { @@ -152,7 +153,7 @@ public LayoutComponentsFilter() { "timed_reaction" ); - final var searchResultShelfHeader = new StartsWithStringFilterGroup( + searchResultShelfHeader = new StringFilterGroup( SettingsEnum.HIDE_SEARCH_RESULT_SHELF_HEADER, "shelf_header.eml" ); @@ -194,7 +195,6 @@ public LayoutComponentsFilter() { artistCard, timedReactions, imageShelf, - searchResultShelfHeader, channelMemberShelf, custom ); @@ -211,6 +211,8 @@ public boolean isFiltered(@Nullable String identifier, String path, byte[] proto if (matchedGroup != custom && exceptions.matches(path)) return false; // Exceptions are not filtered. + if (matchedGroup == searchResultShelfHeader && matchedIndex == 0) return true; + return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex); } diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java index da030a3725..7cfe060b1d 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LithoFilterPatch.java @@ -85,18 +85,6 @@ public FilterGroupResult check(final String string) { } } -class StartsWithStringFilterGroup extends StringFilterGroup { - - public StartsWithStringFilterGroup(final SettingsEnum setting, final String... filters) { - super(setting, filters); - } - - @Override - public FilterGroupResult check(final String string) { - return new FilterGroupResult(setting, isEnabled() && ReVancedUtils.startsWithAny(string, filters)); - } -} - final class CustomFilterGroup extends StringFilterGroup { public CustomFilterGroup(final SettingsEnum setting, final SettingsEnum filter) { diff --git a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java index a145bbfc75..940dd50819 100644 --- a/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java +++ b/app/src/main/java/app/revanced/integrations/utils/ReVancedUtils.java @@ -88,12 +88,6 @@ public static boolean containsAny(@NonNull String value, @NonNull String... targ return false; } - public static boolean startsWithAny(@NonNull String value, @NonNull String... targets) { - for (String string : targets) - if (!string.isEmpty() && value.startsWith(string)) return true; - return false; - } - /** * @return zero, if the resource is not found */ From 3d0fc1d610cdf50bb7cc4687d899e0acbf3fb83e Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 2 Oct 2023 22:15:29 +0200 Subject: [PATCH 63/69] fix: Do not always hide the component --- .../patches/components/LayoutComponentsFilter.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index e197d4c8a2..b2d626510d 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -211,7 +211,8 @@ public boolean isFiltered(@Nullable String identifier, String path, byte[] proto if (matchedGroup != custom && exceptions.matches(path)) return false; // Exceptions are not filtered. - if (matchedGroup == searchResultShelfHeader && matchedIndex == 0) return true; + // TODO: This also hides the feed Shorts shelf header + if (matchedGroup == searchResultShelfHeader && matchedIndex != 0) return false; return super.isFiltered(identifier, path, protobufBufferArray, matchedList, matchedGroup, matchedIndex); } From b280de31957631180f07057cc7e466bd26e2f7fb Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Mon, 2 Oct 2023 22:16:06 +0200 Subject: [PATCH 64/69] feat(YouTube - Hide layout components): Disable hiding search result shelf header by default The reason for this is that it also hides Shorts shelves unintentionally. --- .../java/app/revanced/integrations/settings/SettingsEnum.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java index 5e5c56ffd1..581f934057 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -66,7 +66,7 @@ public enum SettingsEnum { HIDE_FEED_SURVEY("revanced_hide_feed_survey", BOOLEAN, TRUE), HIDE_GRAY_SEPARATOR("revanced_hide_gray_separator", BOOLEAN, TRUE), HIDE_TIMED_REACTIONS("revanced_hide_timed_reactions", BOOLEAN, TRUE), - HIDE_SEARCH_RESULT_SHELF_HEADER("revanced_hide_search_result_shelf_header", BOOLEAN, TRUE), + HIDE_SEARCH_RESULT_SHELF_HEADER("revanced_hide_search_result_shelf_header", BOOLEAN, FALSE), HIDE_NOTIFY_ME_BUTTON("revanced_hide_notify_me_button", BOOLEAN, TRUE), HIDE_JOIN_MEMBERSHIP_BUTTON("revanced_hide_join_membership_button", BOOLEAN, TRUE), HIDE_HIDE_CHANNEL_GUIDELINES("revanced_hide_channel_guidelines", BOOLEAN, TRUE), From a198ef83dd89360db9a16e529be4cba9efedbac9 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 2 Oct 2023 20:20:31 +0000 Subject: [PATCH 65/69] chore(release): 0.118.0-dev.22 [skip ci] # [0.118.0-dev.22](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.21...v0.118.0-dev.22) (2023-10-02) ### Bug Fixes * Do not always hide the component ([3d0fc1d](https://github.com/ReVanced/revanced-integrations/commit/3d0fc1d610cdf50bb7cc4687d899e0acbf3fb83e)) ### Features * **YouTube - Hide layout components:** Disable hiding search result shelf header by default ([b280de3](https://github.com/ReVanced/revanced-integrations/commit/b280de31957631180f07057cc7e466bd26e2f7fb)) --- CHANGELOG.md | 12 ++++++++++++ gradle.properties | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a84b385311..b004914b8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# [0.118.0-dev.22](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.21...v0.118.0-dev.22) (2023-10-02) + + +### Bug Fixes + +* Do not always hide the component ([3d0fc1d](https://github.com/ReVanced/revanced-integrations/commit/3d0fc1d610cdf50bb7cc4687d899e0acbf3fb83e)) + + +### Features + +* **YouTube - Hide layout components:** Disable hiding search result shelf header by default ([b280de3](https://github.com/ReVanced/revanced-integrations/commit/b280de31957631180f07057cc7e466bd26e2f7fb)) + # [0.118.0-dev.21](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.20...v0.118.0-dev.21) (2023-10-02) diff --git a/gradle.properties b/gradle.properties index 4831a7515d..bf03d2e098 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.21 +version = 0.118.0-dev.22 From 4215be4250d195ecf89b041c96834be56c164f34 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Tue, 3 Oct 2023 01:27:27 +0400 Subject: [PATCH 66/69] fix(YouTube - SponsorBlock): Adjust import/export UI text (#491) --- .../settingsmenu/SponsorBlockSettingsFragment.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java b/app/src/main/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java index e1de088de3..456bcdc8a9 100644 --- a/app/src/main/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java +++ b/app/src/main/java/app/revanced/integrations/settingsmenu/SponsorBlockSettingsFragment.java @@ -72,7 +72,7 @@ private void updateUI() { } else if (!SettingsEnum.SB_CREATE_NEW_SEGMENT.getBoolean()) { SponsorBlockViewController.hideNewSegmentLayout(); } - // voting and add new segment buttons automatically shows/hides themselves + // Voting and add new segment buttons automatically shows/hide themselves. sbEnabled.setChecked(enabled); @@ -109,6 +109,12 @@ private void updateUI() { privateUserId.setText(SettingsEnum.SB_PRIVATE_USER_ID.getString()); privateUserId.setEnabled(enabled); + // If the user has a private user id, then include a subtext that mentions not to share it. + String exportSummarySubText = SponsorBlockSettings.userHasSBPrivateId() + ? str("sb_settings_ie_sum_warning") + : ""; + importExport.setSummary(str("sb_settings_ie_sum", exportSummarySubText)); + apiUrl.setEnabled(enabled); importExport.setEnabled(enabled); segmentCategory.setEnabled(enabled); @@ -329,6 +335,7 @@ private void addGeneralCategory(final Context context, PreferenceScreen screen) return false; } SettingsEnum.SB_PRIVATE_USER_ID.saveValue(newUUID); + updateUI(); fetchAndDisplayStats(); return true; }); @@ -375,7 +382,7 @@ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { } }; importExport.setTitle(str("sb_settings_ie")); - importExport.setSummary(str("sb_settings_ie_sum")); + // Summary is set in updateUI() importExport.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); From 6075c9ed17c7220d8ef4a99a44ae1ad42c73c9b3 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Mon, 2 Oct 2023 21:31:31 +0000 Subject: [PATCH 67/69] chore(release): 0.118.0-dev.23 [skip ci] # [0.118.0-dev.23](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.22...v0.118.0-dev.23) (2023-10-02) ### Bug Fixes * **YouTube - SponsorBlock:** Adjust import/export UI text ([#491](https://github.com/ReVanced/revanced-integrations/issues/491)) ([4215be4](https://github.com/ReVanced/revanced-integrations/commit/4215be4250d195ecf89b041c96834be56c164f34)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b004914b8b..b7c0ca6f3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.23](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.22...v0.118.0-dev.23) (2023-10-02) + + +### Bug Fixes + +* **YouTube - SponsorBlock:** Adjust import/export UI text ([#491](https://github.com/ReVanced/revanced-integrations/issues/491)) ([4215be4](https://github.com/ReVanced/revanced-integrations/commit/4215be4250d195ecf89b041c96834be56c164f34)) + # [0.118.0-dev.22](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.21...v0.118.0-dev.22) (2023-10-02) diff --git a/gradle.properties b/gradle.properties index bf03d2e098..376d6c52b9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.22 +version = 0.118.0-dev.23 From bedb02e4f6122f3dcdc106648648eec4d6a3cbe5 Mon Sep 17 00:00:00 2001 From: oSumAtrIX Date: Tue, 3 Oct 2023 03:28:28 +0200 Subject: [PATCH 68/69] fix(YouTube - Hide layout components): Do not hide chapters in feed unexpectedly --- .../patches/components/LayoutComponentsFilter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java index b2d626510d..39be57c924 100644 --- a/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java +++ b/app/src/main/java/app/revanced/integrations/patches/components/LayoutComponentsFilter.java @@ -178,7 +178,6 @@ public LayoutComponentsFilter() { communityPosts, paidContent, latestPosts, - chapters, communityGuidelines, quickActions, expandableMetadata, @@ -201,7 +200,8 @@ public LayoutComponentsFilter() { this.identifierFilterGroupList.addAll( graySeparator, - chipsShelf + chipsShelf, + chapters ); } From 1a702bce601aa8cd12214d2337a3618cca8a8d72 Mon Sep 17 00:00:00 2001 From: semantic-release-bot Date: Tue, 3 Oct 2023 01:32:28 +0000 Subject: [PATCH 69/69] chore(release): 0.118.0-dev.24 [skip ci] # [0.118.0-dev.24](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.23...v0.118.0-dev.24) (2023-10-03) ### Bug Fixes * **YouTube - Hide layout components:** Do not hide chapters in feed unexpectedly ([bedb02e](https://github.com/ReVanced/revanced-integrations/commit/bedb02e4f6122f3dcdc106648648eec4d6a3cbe5)) --- CHANGELOG.md | 7 +++++++ gradle.properties | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7c0ca6f3d..6657e8bdb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [0.118.0-dev.24](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.23...v0.118.0-dev.24) (2023-10-03) + + +### Bug Fixes + +* **YouTube - Hide layout components:** Do not hide chapters in feed unexpectedly ([bedb02e](https://github.com/ReVanced/revanced-integrations/commit/bedb02e4f6122f3dcdc106648648eec4d6a3cbe5)) + # [0.118.0-dev.23](https://github.com/ReVanced/revanced-integrations/compare/v0.118.0-dev.22...v0.118.0-dev.23) (2023-10-02) diff --git a/gradle.properties b/gradle.properties index 376d6c52b9..848e696fac 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ org.gradle.parallel = true org.gradle.caching = true android.useAndroidX = true -version = 0.118.0-dev.23 +version = 0.118.0-dev.24