Skip to content

Commit

Permalink
feat(YouTube Music - Spoof client): Add support for latest versions, …
Browse files Browse the repository at this point in the history
…Remove 'Spoof streaming data' patch

- 'Spoof client' patch now supports YouTube Music 7.25.53+
- 'Spoof client' patch now spoofs as many innerTube contexts as possible, just like the 'Spoof streaming data' patch
- 'Spoof streaming data' patch is no longer a shared patch
- Nevertheless, 'BlockRequestPatch' is still a shared patch, so each setting is located in a shared path (BaseSettings)
- In YouTube Music 7.16.53 or earlier, 'iOS YouTube Music 6.21' is the only client that does not require 'BlockRequestPatch'
- 'iOS YouTube Music 7.04' supports opus codec when 'Enable OPUS codec' is turned on
  • Loading branch information
inotia00 authored and anddea committed Jan 30, 2025
1 parent dd6baa4 commit 295d940
Show file tree
Hide file tree
Showing 26 changed files with 994 additions and 970 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import app.revanced.extension.music.patches.general.ChangeStartPagePatch.StartPage;
import app.revanced.extension.music.patches.misc.AlbumMusicVideoPatch.RedirectType;
import app.revanced.extension.music.patches.misc.client.AppClient.ClientType;
import app.revanced.extension.music.patches.utils.PatchStatus;
import app.revanced.extension.music.sponsorblock.SponsorBlockSettings;
import app.revanced.extension.shared.settings.BaseSettings;
Expand Down Expand Up @@ -185,9 +184,6 @@ public class Settings extends BaseSettings {
public static final EnumSetting<RedirectType> DISABLE_MUSIC_VIDEO_IN_ALBUM_REDIRECT_TYPE = new EnumSetting<>("revanced_disable_music_video_in_album_redirect_type", RedirectType.REDIRECT, true);
public static final BooleanSetting ENABLE_OPUS_CODEC = new BooleanSetting("revanced_enable_opus_codec", FALSE, true);
public static final BooleanSetting SETTINGS_IMPORT_EXPORT = new BooleanSetting("revanced_extended_settings_import_export", FALSE, false);
public static final BooleanSetting SPOOF_CLIENT = new BooleanSetting("revanced_spoof_client", FALSE, true);
public static final EnumSetting<ClientType> SPOOF_CLIENT_TYPE = new EnumSetting<>("revanced_spoof_client_type", ClientType.IOS_MUSIC_6_21, true);


// PreferenceScreen: Return YouTube Dislike
public static final BooleanSetting RYD_ENABLED = new BooleanSetting("revanced_ryd_enabled", TRUE);
Expand Down Expand Up @@ -260,7 +256,6 @@ public class Settings extends BaseSettings {
SETTINGS_IMPORT_EXPORT.key,
SPOOF_APP_VERSION_TARGET.key,
SPOOF_CLIENT_TYPE.key,
SPOOF_STREAMING_DATA_TYPE.key,
RETURN_YOUTUBE_USERNAME_ABOUT.key,
RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT.key,
RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY.key,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import static app.revanced.extension.music.utils.RestartUtils.showRestartDialog;
import static app.revanced.extension.shared.settings.BaseSettings.RETURN_YOUTUBE_USERNAME_DISPLAY_FORMAT;
import static app.revanced.extension.shared.settings.BaseSettings.RETURN_YOUTUBE_USERNAME_YOUTUBE_DATA_API_V3_DEVELOPER_KEY;
import static app.revanced.extension.shared.settings.BaseSettings.SPOOF_STREAMING_DATA_TYPE;
import static app.revanced.extension.shared.settings.Setting.getSettingFromPath;
import static app.revanced.extension.shared.utils.ResourceUtils.getStringArray;
import static app.revanced.extension.shared.utils.StringRef.str;
Expand Down Expand Up @@ -165,7 +164,6 @@ 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(SPOOF_STREAMING_DATA_TYPE)
) {
ResettableListPreference.showDialog(mActivity, enumSetting, 0);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ public static boolean HideFullscreenAdsDefaultBoolean() {
return false;
}

public static boolean SpoofStreamingDataMusic() {
// Replace this with true If the Spoof streaming data patch succeeds in YouTube Music
public static boolean SpoofClient() {
// Replace this with true If the Spoof streaming data patch succeeds in YouTube Music.
return false;
}

public static boolean SpoofStreamingData() {
// Replace this with true If the Spoof streaming data patch succeeds in YouTube.
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package app.revanced.extension.shared.patches.client;

import android.os.Build;

import java.util.Locale;

public class MusicAppClient {

// Audio codec is MP4A.
private static final String CLIENT_VERSION_ANDROID_MUSIC_4_27 = "4.27.53";

// Audio codec is OPUS.
private static final String CLIENT_VERSION_ANDROID_MUSIC_5_29 = "5.29.53";

private static final String PACKAGE_NAME_ANDROID_MUSIC = "com.google.android.apps.youtube.music";
private static final String DEVICE_BRAND_ANDROID_MUSIC = Build.BRAND;
private static final String DEVICE_MAKE_ANDROID_MUSIC = Build.MANUFACTURER;
private static final String DEVICE_MODEL_ANDROID_MUSIC = Build.MODEL;
private static final String BUILD_ID_ANDROID_MUSIC = Build.ID;
private static final String OS_NAME_ANDROID_MUSIC = "Android Automotive";
private static final String OS_VERSION_ANDROID_MUSIC = Build.VERSION.RELEASE;

// Audio codec is MP4A.
private static final String CLIENT_VERSION_IOS_MUSIC_6_21 = "6.21";
private static final String DEVICE_MODEL_IOS_MUSIC_6_21 = "iPhone14,3";
private static final String OS_VERSION_IOS_MUSIC_6_21 = "15.7.1.19H117";
private static final String USER_AGENT_VERSION_IOS_MUSIC_6_21 = "15_7_1";

// Audio codec is OPUS.
private static final String CLIENT_VERSION_IOS_MUSIC_7_04 = "7.04";
private static final String DEVICE_MODEL_IOS_MUSIC_7_04 = "iPhone17,2";
private static final String OS_VERSION_IOS_MUSIC_7_04 = "18.2.1.22C161";
private static final String USER_AGENT_VERSION_IOS_MUSIC_7_04 = "18_2_1";

private static final String PACKAGE_NAME_IOS_MUSIC = "com.google.ios.youtubemusic";
private static final String DEVICE_BRAND_IOS_MUSIC = "Apple";
private static final String DEVICE_MAKE_IOS_MUSIC = "Apple";
private static final String OS_NAME_IOS_MUSIC = "iOS";

private MusicAppClient() {
}

private static String androidUserAgent(String clientVersion) {
return PACKAGE_NAME_ANDROID_MUSIC +
"/" +
clientVersion +
"(Linux; U; Android " +
OS_VERSION_ANDROID_MUSIC +
"; " +
Locale.getDefault() +
"; " +
DEVICE_MODEL_ANDROID_MUSIC +
" Build/" +
BUILD_ID_ANDROID_MUSIC +
") gzip";
}

private static String iOSUserAgent(String clientVersion, String deviceModel, String osVersion) {
return PACKAGE_NAME_IOS_MUSIC +
"/" +
clientVersion +
" (" +
deviceModel +
"; U; CPU iOS " +
osVersion +
" like Mac OS X; " +
Locale.getDefault() +
")";
}

public enum ActionButtonType {
NONE, // No action button (~ 6.14)
YOUTUBE_BUTTON, // Type of action button is YouTubeButton (6.15 ~ 7.16)
LITHO // Type of action button is ComponentHost (7.17 ~)
}

public enum ClientType {
ANDROID_MUSIC_4_27(21,
DEVICE_BRAND_ANDROID_MUSIC,
DEVICE_MAKE_ANDROID_MUSIC,
DEVICE_MODEL_ANDROID_MUSIC,
OS_NAME_ANDROID_MUSIC,
OS_VERSION_ANDROID_MUSIC,
androidUserAgent(CLIENT_VERSION_ANDROID_MUSIC_4_27),
CLIENT_VERSION_ANDROID_MUSIC_4_27,
ActionButtonType.NONE
),
ANDROID_MUSIC_5_29(21,
DEVICE_BRAND_ANDROID_MUSIC,
DEVICE_MAKE_ANDROID_MUSIC,
DEVICE_MODEL_ANDROID_MUSIC,
OS_NAME_ANDROID_MUSIC,
OS_VERSION_ANDROID_MUSIC,
androidUserAgent(CLIENT_VERSION_ANDROID_MUSIC_5_29),
CLIENT_VERSION_ANDROID_MUSIC_5_29,
ActionButtonType.NONE
),
IOS_MUSIC_6_21(
26,
DEVICE_BRAND_IOS_MUSIC,
DEVICE_MAKE_IOS_MUSIC,
DEVICE_MODEL_IOS_MUSIC_6_21,
OS_NAME_IOS_MUSIC,
OS_VERSION_IOS_MUSIC_6_21,
iOSUserAgent(CLIENT_VERSION_IOS_MUSIC_6_21, DEVICE_MODEL_IOS_MUSIC_6_21, USER_AGENT_VERSION_IOS_MUSIC_6_21),
CLIENT_VERSION_IOS_MUSIC_6_21,
ActionButtonType.YOUTUBE_BUTTON
),
IOS_MUSIC_7_04(
26,
DEVICE_BRAND_IOS_MUSIC,
DEVICE_MAKE_IOS_MUSIC,
DEVICE_MODEL_IOS_MUSIC_7_04,
OS_NAME_IOS_MUSIC,
OS_VERSION_IOS_MUSIC_7_04,
iOSUserAgent(CLIENT_VERSION_IOS_MUSIC_7_04, DEVICE_MODEL_IOS_MUSIC_7_04, USER_AGENT_VERSION_IOS_MUSIC_7_04),
CLIENT_VERSION_IOS_MUSIC_7_04,
ActionButtonType.LITHO
);

/**
* YouTube
* <a href="https://github.com/zerodytrash/YouTube-Internal-Clients?tab=readme-ov-file#clients">client type</a>
*/
public final int id;

/**
* Device brand, equivalent to {@link Build#BRAND} (System property: ro.product.vendor.brand)
*/
public final String deviceBrand;

/**
* Device make, equivalent to {@link Build#MANUFACTURER} (System property: ro.product.vendor.manufacturer)
*/
public final String deviceMake;

/**
* Device model, equivalent to {@link Build#MODEL} (System property: ro.product.model)
*/
public final String deviceModel;

/**
* Device OS name.
*/
public final String osName;

/**
* Device OS version.
*/
public final String osVersion;

/**
* Player user-agent.
*/
public final String userAgent;

/**
* App version.
*/
public final String clientVersion;

private final ActionButtonType actionButtonType;

ClientType(int id,
String deviceBrand,
String deviceMake,
String deviceModel,
String osName,
String osVersion,
String userAgent,
String clientVersion,
ActionButtonType actionButtonType
) {
this.id = id;
this.deviceBrand = deviceBrand;
this.deviceMake = deviceMake;
this.deviceModel = deviceModel;
this.clientVersion = clientVersion;
this.osName = osName;
this.osVersion = osVersion;
this.userAgent = userAgent;
this.actionButtonType = actionButtonType;
}

public boolean isYouTubeButton() {
return actionButtonType == ActionButtonType.YOUTUBE_BUTTON;
}
}
}
Loading

0 comments on commit 295d940

Please sign in to comment.