Skip to content

Commit

Permalink
feat(YouTube Music): Add Watch history patch
Browse files Browse the repository at this point in the history
  • Loading branch information
inotia00 authored and anddea committed Feb 3, 2025
1 parent 6e1c6fe commit 30ab671
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,16 @@ public class Settings extends BaseSettings {
ENABLE_CUSTOM_NAVIGATION_BAR_COLOR_VALUE.key,
EXTERNAL_DOWNLOADER_PACKAGE_NAME.key,
HIDE_ACCOUNT_MENU_FILTER_STRINGS.key,
OPEN_DEFAULT_APP_SETTINGS,
OPTIONAL_SPONSOR_BLOCK_SETTINGS_PREFIX,
RETURN_YOUTUBE_USERNAME_ABOUT.key,
RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.key,
RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.key,
SB_API_URL.key,
SETTINGS_IMPORT_EXPORT.key,
SPOOF_APP_VERSION_TARGET.key,
SPOOF_CLIENT_TYPE.key,
RETURN_YOUTUBE_USERNAME_ABOUT.key,
RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.key,
RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.key,
OPEN_DEFAULT_APP_SETTINGS,
OPTIONAL_SPONSOR_BLOCK_SETTINGS_PREFIX
WATCH_HISTORY_TYPE.key,
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static app.revanced.extension.music.settings.Settings.SETTINGS_IMPORT_EXPORT;
import static app.revanced.extension.music.settings.Settings.SPOOF_APP_VERSION_TARGET;
import static app.revanced.extension.music.settings.Settings.SPOOF_CLIENT_TYPE;
import static app.revanced.extension.music.settings.Settings.WATCH_HISTORY_TYPE;
import static app.revanced.extension.music.utils.ExtendedUtils.getDialogBuilder;
import static app.revanced.extension.music.utils.ExtendedUtils.getLayoutParams;
import static app.revanced.extension.music.utils.RestartUtils.showRestartDialog;
Expand Down Expand Up @@ -164,6 +165,7 @@ public void onCreate(Bundle savedInstanceState) {
|| settings.equals(DISABLE_MUSIC_VIDEO_IN_ALBUM_REDIRECT_TYPE)
|| settings.equals(RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT)
|| settings.equals(SPOOF_CLIENT_TYPE)
|| settings.equals(WATCH_HISTORY_TYPE)
) {
ResettableListPreference.showDialog(mActivity, enumSetting, 0);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package app.revanced.extension.youtube.patches.misc;
package app.revanced.extension.shared.patches;

import android.net.Uri;

import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.youtube.settings.Settings;
import app.revanced.extension.shared.settings.BaseSettings;

@SuppressWarnings("unused")
public final class WatchHistoryPatch {
Expand All @@ -18,7 +18,7 @@ public enum WatchHistoryType {
private static final String WWW_TRACKING_URL_AUTHORITY = "www.youtube.com";

public static Uri replaceTrackingUrl(Uri trackingUrl) {
final WatchHistoryType watchHistoryType = Settings.WATCH_HISTORY_TYPE.get();
final WatchHistoryType watchHistoryType = BaseSettings.WATCH_HISTORY_TYPE.get();
if (watchHistoryType != WatchHistoryType.ORIGINAL) {
try {
if (watchHistoryType == WatchHistoryType.REPLACE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static app.revanced.extension.shared.patches.PatchStatus.HideFullscreenAdsDefaultBoolean;

import app.revanced.extension.shared.patches.ReturnYouTubeUsernamePatch.DisplayFormat;
import app.revanced.extension.shared.patches.WatchHistoryPatch.WatchHistoryType;
import app.revanced.extension.shared.patches.client.MusicAppClient;
import app.revanced.extension.shared.patches.client.YouTubeAppClient;
import app.revanced.extension.shared.patches.spoof.SpoofStreamingDataPatch.AudioStreamLanguageOverrideAvailability;
Expand Down Expand Up @@ -59,6 +60,8 @@ public class BaseSettings {
public static final BooleanSetting DISABLE_QUIC_PROTOCOL = new BooleanSetting("revanced_disable_quic_protocol", FALSE, true);

public static final BooleanSetting BYPASS_IMAGE_REGION_RESTRICTIONS = new BooleanSetting("revanced_bypass_image_region_restrictions", FALSE, true);
public static final EnumSetting<WatchHistoryType> WATCH_HISTORY_TYPE = new EnumSetting<>("revanced_watch_history_type", WatchHistoryType.REPLACE);

public static final BooleanSetting RETURN_YOUTUBE_USERNAME_ENABLED = new BooleanSetting("revanced_return_youtube_username_enabled", FALSE, true);
public static final EnumSetting<DisplayFormat> RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT = new EnumSetting<>("revanced_return_youtube_username_display_format", DisplayFormat.USERNAME_ONLY, true);
public static final StringSetting RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY = new StringSetting("revanced_return_youtube_username_youtube_data_api_v3_developer_key", "", true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
import app.revanced.extension.youtube.patches.general.LayoutSwitchPatch.FormFactor;
import app.revanced.extension.youtube.patches.general.MiniplayerPatch;
import app.revanced.extension.youtube.patches.general.YouTubeMusicActionsPatch;
import app.revanced.extension.youtube.patches.misc.WatchHistoryPatch.WatchHistoryType;
import app.revanced.extension.youtube.patches.player.ExitFullscreenPatch.FullscreenMode;
import app.revanced.extension.youtube.patches.shorts.AnimationFeedbackPatch.AnimationType;
import app.revanced.extension.youtube.patches.shorts.ShortsRepeatStatePatch.ShortsLoopBehavior;
Expand Down Expand Up @@ -595,7 +594,6 @@ public class Settings extends BaseSettings {
public static final LongSetting DOUBLE_BACK_TO_CLOSE_TIMEOUT = new LongSetting("revanced_double_back_to_close_timeout", 2000L);

// PreferenceScreen: Miscellaneous - Watch history
public static final EnumSetting<WatchHistoryType> WATCH_HISTORY_TYPE = new EnumSetting<>("revanced_watch_history_type", WatchHistoryType.REPLACE);

// PreferenceScreen: Miscellaneous - Spoof streaming data

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import android.preference.PreferenceManager;
import android.util.AttributeSet;

import app.revanced.extension.shared.patches.WatchHistoryPatch.WatchHistoryType;
import app.revanced.extension.shared.settings.Setting;
import app.revanced.extension.shared.utils.Utils;
import app.revanced.extension.youtube.patches.misc.WatchHistoryPatch.WatchHistoryType;
import app.revanced.extension.youtube.settings.Settings;

@SuppressWarnings({"deprecation", "unused"})
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package app.revanced.patches.music.misc.watchhistory

import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.trackingurlhook.hookWatchHistory
import app.revanced.patches.shared.trackingurlhook.trackingUrlHookPatch
import app.revanced.patches.music.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.music.utils.patch.PatchList.WATCH_HISTORY
import app.revanced.patches.music.utils.settings.CategoryType
import app.revanced.patches.music.utils.settings.addPreferenceWithIntent
import app.revanced.patches.music.utils.settings.settingsPatch

@Suppress("unused")
val watchHistoryPatch = bytecodePatch(
WATCH_HISTORY.title,
WATCH_HISTORY.summary,
) {
compatibleWith(COMPATIBLE_PACKAGE)

dependsOn(
settingsPatch,
trackingUrlHookPatch,
)

execute {
hookWatchHistory()

addPreferenceWithIntent(
CategoryType.MISC,
"revanced_watch_history_type"
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -164,5 +164,9 @@ internal enum class PatchList(
VISUAL_PREFERENCES_ICONS_FOR_YOUTUBE_MUSIC(
"Visual preferences icons for YouTube Music",
"Adds icons to specific preferences in the settings."
),
WATCH_HISTORY(
"Watch history",
"Adds an option to change the domain of the watch history or check its status."
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package app.revanced.patches.shared.trackingurlhook

import app.revanced.util.fingerprint.legacyFingerprint
import app.revanced.util.or
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode

internal val trackingUrlModelFingerprint = legacyFingerprint(
name = "trackingUrlModelFingerprint",
returnType = "Landroid/net/Uri;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
opcodes = listOf(
Opcode.IGET_OBJECT,
Opcode.INVOKE_STATIC,
Opcode.MOVE_RESULT_OBJECT,
),
)

/**
* On YouTube, this class is 'Lcom/google/android/libraries/youtube/innertube/model/player/TrackingUrlModel;'
* On YouTube Music, class names are obfuscated.
*/
internal val trackingUrlModelToStringFingerprint = legacyFingerprint(
name = "trackingUrlModelToStringFingerprint",
returnType = "Ljava/lang/String;",
accessFlags = AccessFlags.PUBLIC or AccessFlags.FINAL,
parameters = emptyList(),
strings = listOf(
"@",
"baseUrl->",
"params->",
"headers->",
)
)
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
package app.revanced.patches.youtube.utils.trackingurlhook
package app.revanced.patches.shared.trackingurlhook

import app.revanced.patcher.extensions.InstructionExtensions.addInstructions
import app.revanced.patcher.extensions.InstructionExtensions.getInstruction
import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patches.shared.extension.Constants.PATCHES_PATH
import app.revanced.util.fingerprint.methodOrThrow
import app.revanced.util.getReference
import app.revanced.util.indexOfFirstInstructionOrThrow
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.instruction.OneRegisterInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference

private const val EXTENSION_WATCH_HISTORY_CLASS_DESCRIPTOR =
"$PATCHES_PATH/WatchHistoryPatch;"

private lateinit var trackingUrlMethod: MutableMethod

/**
* This patch is currently used only for the 'Watch history' patch.
* In some versions, it can be used to forcibly generate 'Watch history'.
*/
val trackingUrlHookPatch = bytecodePatch(
description = "trackingUrlHookPatch"
) {
execute {
trackingUrlMethod = trackingUrlModelFingerprint.methodOrThrow()
trackingUrlMethod =
trackingUrlModelFingerprint.methodOrThrow(trackingUrlModelToStringFingerprint)
}
}

Expand All @@ -44,3 +53,6 @@ internal fun hookTrackingUrl(
smaliInstruction
)
}

internal fun hookWatchHistory() =
hookTrackingUrl("$EXTENSION_WATCH_HISTORY_CLASS_DESCRIPTOR->replaceTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;")
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package app.revanced.patches.youtube.misc.watchhistory

import app.revanced.patcher.patch.bytecodePatch
import app.revanced.patches.shared.trackingurlhook.hookWatchHistory
import app.revanced.patches.shared.trackingurlhook.trackingUrlHookPatch
import app.revanced.patches.youtube.utils.compatibility.Constants.COMPATIBLE_PACKAGE
import app.revanced.patches.youtube.utils.extension.Constants.MISC_PATH
import app.revanced.patches.youtube.utils.patch.PatchList.WATCH_HISTORY
import app.revanced.patches.youtube.utils.settings.ResourceUtils.addPreference
import app.revanced.patches.youtube.utils.settings.settingsPatch
import app.revanced.patches.youtube.utils.trackingurlhook.hookTrackingUrl
import app.revanced.patches.youtube.utils.trackingurlhook.trackingUrlHookPatch

@Suppress("unused")
val watchHistoryPatch = bytecodePatch(
Expand All @@ -23,7 +22,7 @@ val watchHistoryPatch = bytecodePatch(

execute {

hookTrackingUrl("$MISC_PATH/WatchHistoryPatch;->replaceTrackingUrl(Landroid/net/Uri;)Landroid/net/Uri;")
hookWatchHistory()

// region add settings

Expand Down

This file was deleted.

10 changes: 10 additions & 0 deletions patches/src/main/resources/music/settings/host/values/arrays.xml
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,14 @@
<item>ANDROID_VR</item>
<item>ANDROID_MUSIC</item>
</string-array>
<string-array name="revanced_watch_history_type_entries">
<item>@string/revanced_watch_history_type_entry_1</item>
<item>@string/revanced_watch_history_type_entry_2</item>
<item>@string/revanced_watch_history_type_entry_3</item>
</string-array>
<string-array name="revanced_watch_history_type_entry_values">
<item>ORIGINAL</item>
<item>REPLACE</item>
<item>BLOCK</item>
</string-array>
</resources>

0 comments on commit 30ab671

Please sign in to comment.