diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index d2d6e8f3..dc4a07e8 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -21,5 +21,10 @@ jobs: with: destination_branch: 'main' pr_title: 'chore: ${{ env.MESSAGE }}' - pr_body: 'This pull request will ${{ env.MESSAGE }}.' + pr_body: | + This pull request will ${{ env.MESSAGE }}. + + ## Dependencies before merge + + - [] https://github.com/revanced/revanced-patches pr_draft: true \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index e78b7653..86181bbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,38 @@ +# [0.101.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.101.0-dev.1...v0.101.0-dev.2) (2023-03-19) + + +### Bug Fixes + +* **youtube/remember-playback-speed:** allow to not remember playback speed ([#338](https://github.com/revanced/revanced-integrations/issues/338)) ([7627e5d](https://github.com/revanced/revanced-integrations/commit/7627e5d057fdfb5847b2406b609634489efd3cbf)) + +# [0.101.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.100.2-dev.3...v0.101.0-dev.1) (2023-03-17) + + +### Features + +* **youtube/spoof-signature-verification:** automatic signature spoofing ([d16980e](https://github.com/revanced/revanced-integrations/commit/d16980ef2f18b7b5752be36f0183985c6c398ea1)) + +## [0.100.2-dev.3](https://github.com/revanced/revanced-integrations/compare/v0.100.2-dev.2...v0.100.2-dev.3) (2023-03-15) + + +### Bug Fixes + +* **youtube/spoof-signature-verification:** fix audio during home feed video playback ([#336](https://github.com/revanced/revanced-integrations/issues/336)) ([68d0930](https://github.com/revanced/revanced-integrations/commit/68d09305b990b411efffeeb02aa638e59eee9e5d)) + +## [0.100.2-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.100.2-dev.1...v0.100.2-dev.2) (2023-03-14) + + +### Bug Fixes + +* **youtube/return-youtube-dislike:** layout fix for low dpi devices ([#335](https://github.com/revanced/revanced-integrations/issues/335)) ([46e0272](https://github.com/revanced/revanced-integrations/commit/46e0272f9e96e7893e6fbb919d90248f59addaf9)) + +## [0.100.2-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.100.1...v0.100.2-dev.1) (2023-03-14) + + +### Bug Fixes + +* **youtube/return-youtube-dislike:** fix right to left text layout ([#333](https://github.com/revanced/revanced-integrations/issues/333)) ([2dd1431](https://github.com/revanced/revanced-integrations/commit/2dd14313a64930acbb544f4ad971c51dcfbb80e1)) + ## [0.100.1](https://github.com/revanced/revanced-integrations/compare/v0.100.0...v0.100.1) (2023-03-14) diff --git a/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java b/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java new file mode 100644 index 00000000..43e123dc --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/SpoofSignatureVerificationPatch.java @@ -0,0 +1,83 @@ +package app.revanced.integrations.patches; + +import android.widget.Toast; + +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; + +public class SpoofSignatureVerificationPatch { + /** + * Protobuf parameters used by the player. + * Known issue: video preview not showing when using the seekbar. + */ + private static final String PROTOBUF_PARAMETER_GENERAL = "CgIQBg"; + + /** + * Protobuf parameter of shorts and YouTube stories. + * Known issue: captions are positioned on upper area in the player. + */ + private static final String PROTOBUF_PARAMETER_SHORTS = "8AEB"; // "8AEByAMTuAQP" + + /** + * Target Protobuf parameters. + * Used by the generic player. + */ + private static final String PROTOBUF_PARAMETER_TARGET = "YADI"; + + /** + * Injection point. + * + * @param originalValue originalValue protobuf parameter + */ + public static String overrideProtobufParameter(String originalValue) { + try { + if (!SettingsEnum.SIGNATURE_SPOOFING.getBoolean()) { + return originalValue; + } + LogHelper.printDebug(() -> "Original protobuf parameter value: " + originalValue); + if (originalValue.startsWith(PROTOBUF_PARAMETER_TARGET) || originalValue.isEmpty()) { + return PROTOBUF_PARAMETER_SHORTS; + } + } catch (Exception ex) { + LogHelper.printException(() -> "overrideProtobufParameter failure", ex); + } + + return originalValue; + } + + + /** + * Injection point. Runs off the main thread. + *
+ * Used to check the response code of video playback requests made by YouTube. + * Response code of interest is 403 that indicate a signature verification failure for the current request + * + * @param responseCode HTTP status code of the completed YouTube connection + */ + public static void onResponse(int responseCode) { + try { + if (responseCode < 400 || responseCode >= 500) { + return; // everything normal + } + LogHelper.printDebug(() -> "YouTube HTTP status code: " + responseCode); + + if (SettingsEnum.SIGNATURE_SPOOFING.getBoolean()) { + return; // already enabled + } + + SettingsEnum.SIGNATURE_SPOOFING.saveValue(true); + ReVancedUtils.runOnMainThread(() -> { + Toast.makeText( + ReVancedUtils.getContext(), + "Spoofing app signature to prevent playback issues", Toast.LENGTH_LONG + ).show(); + // it would be great if the video could be forcefully reloaded, but currently there is no code to do this + }); + + } catch (Exception ex) { + LogHelper.printException(() -> "onResponse failure", ex); + } + } + +} diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackRatePatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackRatePatch.java deleted file mode 100644 index b68ff784..00000000 --- a/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackRatePatch.java +++ /dev/null @@ -1,32 +0,0 @@ -package app.revanced.integrations.patches.playback.speed; - -import static app.revanced.integrations.utils.SharedPrefHelper.SharedPrefNames.REVANCED_PREFS; -import static app.revanced.integrations.utils.SharedPrefHelper.getFloat; -import static app.revanced.integrations.utils.SharedPrefHelper.saveFloat; - -import android.widget.Toast; - -import app.revanced.integrations.settings.SettingsEnum; -import app.revanced.integrations.utils.LogHelper; -import app.revanced.integrations.utils.ReVancedUtils; - - -public final class RememberPlaybackRatePatch { - private static final String REMEMBERED_PLAYBACK_RATE_PREFERENCE_KEY = "revanced_remember_playback_rate_last_value"; - - public static void rememberPlaybackRate(final float selectedPlaybackRate) { - if (!SettingsEnum.REMEMBER_PLAYBACK_RATE_SELECTED.getBoolean()) return; - - Toast.makeText(ReVancedUtils.getContext(), "Playback rate will be remembered", Toast.LENGTH_SHORT).show(); - - LogHelper.printDebug(() -> "Remembering playback rate: " + selectedPlaybackRate); - saveFloat(REVANCED_PREFS, REMEMBERED_PLAYBACK_RATE_PREFERENCE_KEY, selectedPlaybackRate); - } - - public static float getRememberedPlaybackRate() { - final var playbackRateOverride = getFloat(REVANCED_PREFS, REMEMBERED_PLAYBACK_RATE_PREFERENCE_KEY, -2f); - - LogHelper.printDebug(() -> "Overriding playback rate: " + playbackRateOverride); - return playbackRateOverride; - } -} diff --git a/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java b/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java new file mode 100644 index 00000000..c1d4a8ad --- /dev/null +++ b/app/src/main/java/app/revanced/integrations/patches/playback/speed/RememberPlaybackSpeedPatch.java @@ -0,0 +1,83 @@ +package app.revanced.integrations.patches.playback.speed; + +import android.widget.Toast; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import app.revanced.integrations.settings.SettingsEnum; +import app.revanced.integrations.utils.LogHelper; +import app.revanced.integrations.utils.ReVancedUtils; + +public final class RememberPlaybackSpeedPatch { + + /** + * The current playback speed + */ + private static float currentPlaybackSpeed = getLastRememberedPlaybackSpeed(); + + private final static float DEFAULT_PLAYBACK_SPEED = (float) SettingsEnum.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_VALUE.getDefaultValue(); + + @Nullable + private static String currentVideoId; + + private static void showToast(final String message) { + Toast.makeText(ReVancedUtils.getContext(), message, Toast.LENGTH_LONG).show(); + } + + private static float getLastRememberedPlaybackSpeed() { + return SettingsEnum.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_VALUE.getFloat(); + } + + private static void rememberPlaybackSpeed() { + SettingsEnum.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_VALUE.saveValue(currentPlaybackSpeed); + } + + private static boolean rememberLastSelectedPlaybackSpeed() { + return SettingsEnum.REMEMBER_PLAYBACK_SPEED_LAST_SELECTED.getBoolean(); + } + + /** + * Injection point. + * Called when a new video loads. + */ + public static void newVideoLoaded(@NonNull String videoId) { + if (videoId.equals(currentVideoId)) { + return; + } + + currentVideoId = videoId; + currentPlaybackSpeed = getLastRememberedPlaybackSpeed(); + } + + /** + * Injection point. + * Called when a playback speed is selected. + * + * @param playbackSpeed The playback speed to set. + */ + public static void setPlaybackSpeed(final float playbackSpeed) { + LogHelper.printDebug(() -> "Playback speed changed to: " + playbackSpeed); + + currentPlaybackSpeed = playbackSpeed; + + if (rememberLastSelectedPlaybackSpeed()) { + rememberPlaybackSpeed(); + + showToast("Remembering playback speed: " + playbackSpeed + "x"); + } else { + if (getLastRememberedPlaybackSpeed() == DEFAULT_PLAYBACK_SPEED) return; + + showToast("Applying playback speed: " + playbackSpeed + "x"); + } + } + + /** + * Injection point. + * Called when playback first starts, + * and also called immediately after the user selects a new video speed. + * + * @return The currently set playback speed. + */ + public static float getCurrentPlaybackSpeed() { + return currentPlaybackSpeed; + } +} 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 158a0226..f66180eb 100644 --- a/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java +++ b/app/src/main/java/app/revanced/integrations/returnyoutubedislike/ReturnYouTubeDislike.java @@ -16,6 +16,8 @@ import android.text.SpannableString; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.style.ImageSpan; +import android.util.DisplayMetrics; +import android.util.TypedValue; import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; @@ -429,19 +431,22 @@ public class ReturnYouTubeDislike { final int separatorColor = ThemeHelper.isDarkTheme() ? 0x29AAAAAA // transparent dark gray : 0xFFD9D9D9; // light gray + DisplayMetrics dp = ReVancedUtils.getContext().getResources().getDisplayMetrics(); if (!compactLayout) { // left separator - final Rect leftSeparatorBounds = new Rect(0, 0, 3, 54); + final Rect leftSeparatorBounds = new Rect(0, 0, + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1.2f, dp), + (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 18, dp)); String leftSeparatorString = ReVancedUtils.isRightToLeftTextLayout() - ? "\u200F " // u200F = right to left character - : "\u2FF0 "; // u2FF0 = left to right character + ? "\u200F " // u200F = right to left character + : "\u200E "; // u200E = left to right character Spannable leftSeparatorSpan = new SpannableString(leftSeparatorString); ShapeDrawable shapeDrawable = new ShapeDrawable(new RectShape()); shapeDrawable.getPaint().setColor(separatorColor); shapeDrawable.setBounds(leftSeparatorBounds); - leftSeparatorSpan.setSpan(new VerticallyCenteredImageSpan(shapeDrawable), 0, 1, - Spannable.SPAN_INCLUSIVE_EXCLUSIVE); + leftSeparatorSpan.setSpan(new VerticallyCenteredImageSpan(shapeDrawable), 1, 2, + Spannable.SPAN_INCLUSIVE_EXCLUSIVE); // drawable cannot overwrite RTL or LTR character builder.append(leftSeparatorSpan); } @@ -453,7 +458,8 @@ public class ReturnYouTubeDislike { ? " " + MIDDLE_SEPARATOR_CHARACTER + " " : " \u2009" + MIDDLE_SEPARATOR_CHARACTER + "\u2009 "; // u2009 = 'narrow space' character final int shapeInsertionIndex = middleSeparatorString.length() / 2; - final Rect middleSeparatorBounds = new Rect(0, 0, 10, 10); + final int middleSeparatorSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3.7f, dp); + final Rect middleSeparatorBounds = new Rect(0, 0, middleSeparatorSize, middleSeparatorSize); Spannable middleSeparatorSpan = new SpannableString(middleSeparatorString); ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape()); shapeDrawable.getPaint().setColor(separatorColor); 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 e427e5bd..e2cac092 100644 --- a/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java +++ b/app/src/main/java/app/revanced/integrations/settings/SettingsEnum.java @@ -18,11 +18,11 @@ public enum SettingsEnum { // Video settings OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS("revanced_use_old_style_quality_settings", true, ReturnType.BOOLEAN), REMEMBER_VIDEO_QUALITY_LAST_SELECTED("revanced_remember_video_quality_last_selected", true, ReturnType.BOOLEAN), - REMEMBER_PLAYBACK_RATE_SELECTED("revanced_remember_playback_rate_selected", true, ReturnType.BOOLEAN), - + REMEMBER_PLAYBACK_SPEED_LAST_SELECTED("revanced_remember_playback_speed_last_selected", true, ReturnType.BOOLEAN), + REMEMBER_PLAYBACK_SPEED_LAST_SELECTED_VALUE("revanced_remember_playback_speed_last_selected_value", 1.0f, ReturnType.FLOAT), + // TODO: Unused currently // Whitelist settings - //ToDo: Not used atm, Patch missing ENABLE_WHITELIST("revanced_whitelist_ads_enabled", false, ReturnType.BOOLEAN), // Ad settings @@ -96,7 +96,7 @@ public enum SettingsEnum { HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", true, ReturnType.BOOLEAN, true), // Misc. Settings - FIX_PLAYBACK("revanced_fix_playback", false, ReturnType.BOOLEAN), + SIGNATURE_SPOOFING("revanced_spoof_signature_verification", false, ReturnType.BOOLEAN), CAPTIONS_ENABLED("revanced_autocaptions_enabled", false, ReturnType.BOOLEAN), PREFERRED_AUTO_REPEAT("revanced_pref_auto_repeat", false, ReturnType.BOOLEAN), USE_HDR_AUTO_BRIGHTNESS("revanced_pref_hdr_autobrightness", true, ReturnType.BOOLEAN), diff --git a/gradle.properties b/gradle.properties index 80bf1b25..8d1540fc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.jvmargs = -Xmx2048m android.useAndroidX = true -version = 0.100.1 +version = 0.101.0-dev.2