Skip to content

Commit

Permalink
Merge branch 'inotia00:dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
YT-Advanced authored Dec 8, 2024
2 parents 52b80a4 + 041bb1c commit 089ae1d
Show file tree
Hide file tree
Showing 77 changed files with 2,144 additions and 1,264 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ See the [documentation](https://github.com/inotia00/revanced-documentation#readm
| `Settings for YouTube Music` | Applies mandatory patches to implement ReVanced Extended settings into the application. | 6.20.51 ~ 7.16.53 |
| `SponsorBlock` | Adds options to enable and configure SponsorBlock, which can skip undesired video segments, such as non-music sections. | 6.20.51 ~ 7.16.53 |
| `Spoof app version` | Adds options to spoof the YouTube Music client version. This can remove the radio mode restriction in Canadian regions or disable real-time lyrics. | 6.20.51 ~ 7.16.53 |
| `Spoof client` | Adds options to spoof the client to allow track playback. | 6.20.51 ~ 7.16.53 |
| `Translations for YouTube Music` | Add translations or remove string resources. | 6.20.51 ~ 7.16.53 |
| `Video playback` | Adds options to customize settings related to video playback, such as default video quality and playback speed. | 6.20.51 ~ 7.16.53 |
| `Visual preferences icons for YouTube Music` | Adds icons to specific preferences in the settings. | 6.20.51 ~ 7.16.53 |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package app.revanced.extension.music.patches.misc;

import app.revanced.extension.music.patches.misc.client.AppClient.ClientType;
import app.revanced.extension.music.settings.Settings;

@SuppressWarnings("unused")
public class SpoofClientPatch {
private static final boolean SPOOF_CLIENT_ENABLED = Settings.SPOOF_CLIENT.get();
private static final ClientType clientType = ClientType.IOS_MUSIC;

/**
* Injection point.
*/
public static int getClientTypeId(int originalClientTypeId) {
if (SPOOF_CLIENT_ENABLED) {
return clientType.id;
}

return originalClientTypeId;
}

/**
* Injection point.
*/
public static String getClientVersion(String originalClientVersion) {
if (SPOOF_CLIENT_ENABLED) {
return clientType.clientVersion;
}

return originalClientVersion;
}

/**
* Injection point.
*/
public static String getClientModel(String originalClientModel) {
if (SPOOF_CLIENT_ENABLED) {
return clientType.deviceModel;
}

return originalClientModel;
}

/**
* Injection point.
*/
public static String getOsVersion(String originalOsVersion) {
if (SPOOF_CLIENT_ENABLED) {
return clientType.osVersion;
}

return originalOsVersion;
}

/**
* Injection point.
*/
public static String getUserAgent(String originalUserAgent) {
if (SPOOF_CLIENT_ENABLED) {
return clientType.userAgent;
}

return originalUserAgent;
}

/**
* Injection point.
*/
public static boolean isClientSpoofingEnabled() {
return SPOOF_CLIENT_ENABLED;
}

/**
* Injection point.
* When spoofing the client to iOS, the playback speed menu is missing from the player response.
* Return true to force create the playback speed menu.
*/
public static boolean forceCreatePlaybackSpeedMenu(boolean original) {
if (SPOOF_CLIENT_ENABLED) {
return true;
}
return original;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package app.revanced.extension.music.patches.misc.client;

import android.os.Build;

import androidx.annotation.Nullable;

public class AppClient {

/**
* The hardcoded client version of the iOS app used for InnerTube requests with this client.
*
* <p>
* It can be extracted by getting the latest release version of the app on
* <a href="https://apps.apple.com/us/app/music-watch-listen-stream/id544007664/">the App
* Store page of the YouTube app</a>, in the {@code What’s New} section.
* </p>
*/
private static final String CLIENT_VERSION_IOS = "6.21";
private static final String DEVICE_MAKE_IOS = "Apple";
/**
* See <a href="https://gist.github.com/adamawolf/3048717">this GitHub Gist</a> for more
* information.
* </p>
*/
private static final String DEVICE_MODEL_IOS = "iPhone16,2";
private static final String OS_NAME_IOS = "iOS";
private static final String OS_VERSION_IOS = "17.7.2.21H221";
private static final String USER_AGENT_VERSION_IOS = "17_7_2";
private static final String USER_AGENT_IOS = "com.google.ios.youtubemusic/" +
CLIENT_VERSION_IOS +
"(" +
DEVICE_MODEL_IOS +
"; U; CPU iOS " +
USER_AGENT_VERSION_IOS +
" like Mac OS X)";

private AppClient() {
}

public enum ClientType {
IOS_MUSIC(26,
DEVICE_MAKE_IOS,
DEVICE_MODEL_IOS,
CLIENT_VERSION_IOS,
OS_NAME_IOS,
OS_VERSION_IOS,
null,
USER_AGENT_IOS,
true
);

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

/**
* Device manufacturer.
*/
@Nullable
public final String deviceMake;

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

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

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

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

/**
* Android SDK version, equivalent to {@link Build.VERSION#SDK} (System property: ro.build.version.sdk)
* Field is null if not applicable.
*/
public final Integer androidSdkVersion;

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

/**
* If the client can access the API logged in.
*/
public final boolean canLogin;

ClientType(int id,
@Nullable String deviceMake,
String deviceModel,
String clientVersion,
@Nullable String osName,
String osVersion,
Integer androidSdkVersion,
String userAgent,
boolean canLogin
) {
this.id = id;
this.deviceMake = deviceMake;
this.deviceModel = deviceModel;
this.clientVersion = clientVersion;
this.osName = osName;
this.osVersion = osVersion;
this.androidSdkVersion = androidSdkVersion;
this.userAgent = userAgent;
this.canLogin = canLogin;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ public class Settings extends BaseSettings {
public static final BooleanSetting CHANGE_SHARE_SHEET = new BooleanSetting("revanced_change_share_sheet", FALSE, true);
public static final BooleanSetting DISABLE_CAIRO_SPLASH_ANIMATION = new BooleanSetting("revanced_disable_cairo_splash_animation", FALSE, true);
public static final BooleanSetting ENABLE_OPUS_CODEC = new BooleanSetting("revanced_enable_opus_codec", FALSE, true);
public static final BooleanSetting SPOOF_CLIENT = new BooleanSetting("revanced_spoof_client", FALSE, true);
public static final BooleanSetting SETTINGS_IMPORT_EXPORT = new BooleanSetting("revanced_extended_settings_import_export", FALSE, false);


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package app.revanced.extension.shared.patches;

@SuppressWarnings("unused")
public class PatchStatus {
public static boolean HideFullscreenAdsDefaultBoolean() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import static java.lang.Boolean.FALSE;
import static java.lang.Boolean.TRUE;

import static app.revanced.extension.shared.patches.PatchStatus.HideFullscreenAdsDefaultBoolean;

import app.revanced.extension.shared.patches.ReturnYouTubeUsernamePatch.DisplayFormat;

/**
Expand All @@ -23,7 +25,7 @@ public class BaseSettings {
/**
* These settings are used by YouTube and YouTube Music.
*/
public static final BooleanSetting HIDE_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", TRUE, true);
public static final BooleanSetting HIDE_FULLSCREEN_ADS = new BooleanSetting("revanced_hide_fullscreen_ads", HideFullscreenAdsDefaultBoolean(), true);
public static final BooleanSetting HIDE_PROMOTION_ALERT_BANNER = new BooleanSetting("revanced_hide_promotion_alert_banner", TRUE);

public static final BooleanSetting DISABLE_AUTO_CAPTIONS = new BooleanSetting("revanced_disable_auto_captions", FALSE, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import app.revanced.extension.shared.patches.components.Filter;
import app.revanced.extension.shared.patches.components.StringFilterGroup;
import app.revanced.extension.shared.patches.components.StringFilterGroupList;
import app.revanced.extension.shared.utils.Logger;
import app.revanced.extension.shared.utils.StringTrieSearch;
import app.revanced.extension.youtube.settings.Settings;

Expand All @@ -26,7 +27,7 @@ public final class FeedComponentsFilter extends Filter {

private static final ByteArrayFilterGroup mixPlaylists =
new ByteArrayFilterGroup(
Settings.HIDE_MIX_PLAYLISTS,
null,
"&list="
);
private static final ByteArrayFilterGroup mixPlaylistsBufferExceptions =
Expand Down Expand Up @@ -229,11 +230,20 @@ public FeedComponentsFilter() {
* <p>
* Called from a different place then the other filters.
*/
public static boolean filterMixPlaylists(final Object conversionContext, final byte[] bytes) {
return bytes != null
&& mixPlaylists.check(bytes).isFiltered()
&& !mixPlaylistsBufferExceptions.check(bytes).isFiltered()
&& !mixPlaylistsContextExceptions.matches(conversionContext.toString());
public static boolean filterMixPlaylists(final Object conversionContext, @Nullable final byte[] bytes) {
try {
if (!Settings.HIDE_MIX_PLAYLISTS.get()) {
return false;
}
return bytes != null
&& mixPlaylists.check(bytes).isFiltered()
&& !mixPlaylistsBufferExceptions.check(bytes).isFiltered()
&& !mixPlaylistsContextExceptions.matches(conversionContext.toString());
} catch (Exception ex) {
Logger.printException(() -> "filterMixPlaylists failure", ex);
}

return false;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,10 @@ public ReturnYouTubeDislikeFilterPatch() {
new StringFilterGroup(null, "|shorts_dislike_button.eml")
);

// After the likes icon name is some binary data and then the video id for that specific short.
// After the button identifiers is binary data and then the video id for that specific short.
videoIdFilterGroup.addAll(
// on_shadowed = Video was previously like/disliked before opening.
// off_shadowed = Video was not previously liked/disliked before opening.
new ByteArrayFilterGroup(null, "ic_right_like_on_shadowed"),
new ByteArrayFilterGroup(null, "ic_right_like_off_shadowed"),

new ByteArrayFilterGroup(null, "ic_right_dislike_on_shadowed"),
new ByteArrayFilterGroup(null, "ic_right_dislike_off_shadowed")
new ByteArrayFilterGroup(null, "id.reel_like_button"),
new ByteArrayFilterGroup(null, "id.reel_dislike_button")
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@

@SuppressWarnings("unused")
public final class ShortsButtonFilter extends Filter {
private final static String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml";
private final static String REEL_LIVE_HEADER_PATH = "immersive_live_header.eml";
private static final String REEL_CHANNEL_BAR_PATH = "reel_channel_bar.eml";
private static final String REEL_LIVE_HEADER_PATH = "immersive_live_header.eml";
/**
* For paid promotion label and subscribe button that appears in the channel bar.
*/
private final static String REEL_METAPANEL_PATH = "reel_metapanel.eml";
private static final String REEL_METAPANEL_PATH = "reel_metapanel.eml";

private final static String SHORTS_PAUSED_STATE_BUTTON_PATH = "|ScrollableContainerType|ContainerType|button.eml|";
private static final String SHORTS_PAUSED_STATE_BUTTON_PATH = "|ScrollableContainerType|ContainerType|button.eml|";

private final StringFilterGroup subscribeButton;
private final StringFilterGroup joinButton;
Expand All @@ -30,7 +30,7 @@ public final class ShortsButtonFilter extends Filter {
private final StringFilterGroup suggestedAction;
private final ByteArrayFilterGroupList suggestedActionsGroupList = new ByteArrayFilterGroupList();

private final StringFilterGroup actionBar;
private final StringFilterGroup actionButton;
private final ByteArrayFilterGroupList videoActionButtonGroupList = new ByteArrayFilterGroupList();

private final ByteArrayFilterGroup useThisSoundButton = new ByteArrayFilterGroup(
Expand Down Expand Up @@ -106,9 +106,9 @@ public ShortsButtonFilter() {
"subscribe_button"
);

actionBar = new StringFilterGroup(
actionButton = new StringFilterGroup(
null,
"shorts_action_bar"
"shorts_video_action_button.eml"
);

suggestedAction = new StringFilterGroup(
Expand All @@ -117,7 +117,7 @@ public ShortsButtonFilter() {
);

addPathCallbacks(
suggestedAction, actionBar, joinButton, subscribeButton, metaPanelButton,
suggestedAction, actionButton, joinButton, subscribeButton, metaPanelButton,
paidPromotionButton, pausedOverlayButtons, channelBar, fullVideoLinkLabel,
videoTitle, reelSoundMetadata, infoPanel, liveHeader, stickers
);
Expand Down Expand Up @@ -239,7 +239,7 @@ public boolean isFiltered(String path, @Nullable String identifier, String allVa
}

// Video action buttons (like, dislike, comment, share, remix) have the same path.
if (matchedGroup == actionBar) {
if (matchedGroup == actionButton) {
if (videoActionButtonGroupList.check(protobufBufferArray).isFiltered()) {
return super.isFiltered(path, identifier, allValue, protobufBufferArray, matchedGroup, contentType, contentIndex);
}
Expand Down
Loading

0 comments on commit 089ae1d

Please sign in to comment.