JulienMaille / spicetify-dynamic-theme

A theme for Spicetify with support for light/dark modes and album art based colors.
MIT License
295 stars 25 forks source link

Patching Dark Mode via Script doesn't work anymore #102

Open rjmolina13 opened 2 days ago

rjmolina13 commented 2 days ago

Describe the bug Patching the Forced Dark Mode in Spotify via Theme's script doesn't work anymore even when tried to fix the script itself, results in Spotify not opening.

To Reproduce Steps to reproduce the behavior:

  1. Download and install latest Spotify version via Spotify Web Installer .dmg.
  2. Download and install latest Spicetify version via MacOS .sh script.
  3. Download and install latest spicetify-dynamic-theme via MacOS .sh script.
  4. Run the Follow system dark/light theme patch for MacOS. Error shown in screenshot.
  5. Even fiddled around the patch script and tried to fix the illegal byte sequence as I think the .plist isn't being parsed properly.

from

# Patch the binary
sed -i.bak 's/force-dark-mode/\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/' "$path"

to

# Patch the binary
LC_CTYPE=C sed -i.bak 's/force-dark-mode/\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/' "$path"
# sed -i.bak 's/force-dark-mode/\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/' "$path"
  1. The script works and patches Spotify but results in Spotify not opening.

Screenshots

image image image

Desktop Setup

Logs

 document.domain mutation is ignored because the surrounding agent cluster is origin-keyed.
(anonymous) @ index.html:1
CircularSp-Book.woff2:1 

       Failed to load resource: net::ERR_NAME_NOT_RESOLVED
CircularSpTitle-Bold.woff2:1 

       Failed to load resource: net::ERR_NAME_NOT_RESOLVED
CircularSp-Bold.woff2:1 

       Failed to load resource: net::ERR_NAME_NOT_RESOLVED
CircularSpTitle-Black.woff2:1 

       Failed to load resource: net::ERR_NAME_NOT_RESOLVED
spicetifyWrapper.js:453 [spicetifyWrapper] Waiting for required webpack modules to load
4151.css:1 

       Failed to load resource: net::ERR_NAME_NOT_RESOLVED
favicon.ico:1 

       Failed to load resource: net::ERR_NAME_NOT_RESOLVED
expFeatures.js:159 [spicetify-exp-features] Removed enableMerchHubWrappedTakeover from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enablePickAndShuffle from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableRTPTrackCredits from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enablePlaylistEsperanto from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enablePartialPlaylistEsperantoForAudiobooks from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableTrackInternalLinkRecommender from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableRichPlaylistPages from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableNewArtistEventsPage from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableVerticalMetricsFonts from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableILRShow from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed searchVisibilityTest from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableHifi from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableAudiobooks from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableSearchV3 from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableRightSidebarTransitionAnimations from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableEmployeeLeaderboardArtists from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableEmployeeLeaderboardPlaylist2022 from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableWhatsNewFeedMainView from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableNonBrowseMerchHub from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enablePuffin from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableEncoreListRowMigration from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableNewConnectBar from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableDevicePickerSidePanel from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableInternalTrackSearch from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed forceYourDJHomeCard from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableHomeSubfeeds from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableEncorePlaybackButtons from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableEightShortcuts from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableEncoreCards from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableConcertEntityPathfinderDWP from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableGlobalNavBar from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableILRAlbumOnDWP from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableBanArtistAction from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableLearningHomeCard from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:159 [spicetify-exp-features] Removed enableYLXPrereleases from override list
waitForRemoteConfigResolver @ expFeatures.js:159
expFeatures.js:258 enableConnectDevicesAPI true Object
expFeatures.js:258 enableInteractionLogger false Object
expFeatures.js:258 enableNewShuffleModeOrder false Object
expFeatures.js:258 enableDeeplinkSaveForLaterIntent true Object
expFeatures.js:258 enablePodcastSpeedControlEndpoint esperanto Object
expFeatures.js:258 enableLiveEventsFeedLocationOnboarding true Object
expFeatures.js:258 enableHomeImpressions true Object
expFeatures.js:258 enableSearchImpressions true Object
expFeatures.js:258 enableConcertGenres true Object
expFeatures.js:258 enableConcertPageGenres true Object
expFeatures.js:258 enablePremiumPagePrepaid true Object
expFeatures.js:258 enableConnectTransferAPI true Object
expFeatures.js:258 enableConnectDiscoveryAPI true Object
expFeatures.js:258 enableConnectDeviceManagementAPI true Object
expFeatures.js:258 enableQueueOnRightPanelAnimations true Object
expFeatures.js:258 enableArtistBans true Object
expFeatures.js:258 enableHybridHome true Object
expFeatures.js:258 enableShowRating true Object
expFeatures.js:258 enableCanvasNpv canvas-play-loop Object
expFeatures.js:258 enableHybridHomeFeedBaseline true Object
expFeatures.js:258 enableNpvCreditsImpressions true Object
expFeatures.js:258 enableCenteredLayout true Object
expFeatures.js:258 enableNewConcertFeed true Object
expFeatures.js:258 enableVenuePages true Object
expFeatures.js:258 enableArtistNPVImpressions true Object
expFeatures.js:258 enableVideoAutoplayHome true Object
expFeatures.js:258 shareButtonPositioning NPV_VISIBLE_ON_HOVER Object
expFeatures.js:258 enableHomeSubfeedFeedBaseline true Object
expFeatures.js:258 enableYourEpisodesListPlatform true Object
expFeatures.js:258 enableRecentSearchesDropdown true Object
expFeatures.js:258 enableConcertUserLocationSelector true Object
expFeatures.js:258 enableUpdatesViaEsperanto true Object
expFeatures.js:258 disableLatestEpisodeOnShow true Object
expFeatures.js:258 enableLazyHomeShelvesDWP false Object
spicetifyWrapper.js:474 [spicetifyWrapper] All required webpack modules loaded
extension.js:8 Initializing Spicetify Marketplace v1.0.2
sidebarConfig.js:169 Uncaught (in promise) TypeError: Spicetify.Snackbar?.enqueueCustomSnackbar is not a function
    at sidebarConfig.js:169:24
2vendor~xpui.js:1 Uncaught (in promise) PlaybackError: No supported keysystem was found.
    at qt._handlePlayerInitError (vendor~xpui.js:1:499716)
extension.js:8 Loaded Marketplace extension
3vendor~xpui.js:1 ButtonTertiary must have an aria-label or aria-labelledby attribute defined when using the iconOnly prop in order to be accessible.
l @ vendor~xpui.js:1
gew1-spclient.spotify.com/remote-config-resolver/v3/configuration:1 

       Failed to load resource: the server responded with a status of 404 ()
vendor~xpui.js:1 provider:transport resolve error k Object
h @ vendor~xpui.js:1
index.html:1 Uncaught (in promise) k
vendor~xpui.js:1 ButtonTertiary must have an aria-label or aria-labelledby attribute defined when using the iconOnly prop in order to be accessible.
l @ vendor~xpui.js:1
16The resource <URL> was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.
2vendor~xpui.js:1 ButtonTertiary must have an aria-label or aria-labelledby attribute defined when using the iconOnly prop in order to be accessible.
l @ vendor~xpui.js:1
16vendor~xpui.js:1 Uncaught (in promise) PlaybackError: No supported keysystem was found.
    at qt._handlePlayerInitError (vendor~xpui.js:1:499716)
vendor~xpui.js:1 ButtonTertiary must have an aria-label or aria-labelledby attribute defined when using the iconOnly prop in order to be accessible.
l @ vendor~xpui.js:1
2vendor~xpui.js:1 Uncaught (in promise) PlaybackError: No supported keysystem was found.
    at qt._handlePlayerInitError (vendor~xpui.js:1:499716)
default-dynamic.js:296 Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLCanvasElement or HTMLImageElement or HTMLVideoElement or ImageBitmap or OffscreenCanvas or SVGImageElement or VideoFrame)'.
    at img.onload (default-dynamic.js:296:17)
4vendor~xpui.js:1 Uncaught (in promise) PlaybackError: No supported keysystem was found.
    at qt._handlePlayerInitError (vendor~xpui.js:1:499716)
default-dynamic.js:296 Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLCanvasElement or HTMLImageElement or HTMLVideoElement or ImageBitmap or OffscreenCanvas or SVGImageElement or VideoFrame)'.
    at img.onload (default-dynamic.js:296:17)
8vendor~xpui.js:1 Uncaught (in promise) PlaybackError: No supported keysystem was found.
    at qt._handlePlayerInitError (vendor~xpui.js:1:499716)
index.html:1 document.domain mutation is ignored because the surrounding agent cluster is origin-keyed.
(anonymous) @ index.html:1
JulienMaille commented 1 day ago

@Covkie do you have the same issue on Linux? @rjmolina13 can you upload the file before and after applying the patch? What if you try LC_CTYPE=C sed -i.bak 's/force-dark-mode/force-dark-nope/' "$path"

rjmolina13 commented 1 hour ago

@JulienMaille Again, latest Spotify version for Mac. Before patch: Spotify_before.zip

After patch: Spotify_after.zip

Those are with my patch.


But with LC_CTYPE=C sed -i.bak 's/force-dark-mode/force-dark-nope/' "$path" it now works!!

image image image

Now, auto theme switching between Light and Dark mode works! https://github.com/user-attachments/assets/656b7582-b351-4c43-8800-e070d4692311


Edit: So I think what happened is that changing the hex to 00's effectively damages the structure of the binary file. But with only replacing one word of the string the file structure is intact while altering the flag's functionality.

rjmolina13 commented 1 hour ago

I might be wrong, but my thinking is: if the first patch; sed -i.bak 's/force-dark-mode/\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/' "$path" works on some versions, then the alternative patch; LC_CTYPE=C sed -i.bak 's/force-dark-mode/force-dark-nope/' "$path" should work on those versions where the first patch doesn’t.


Here I have updated the script to include both patches, with error handling and patching fallback. (Also added colors.) It tries the first patch then if errors out with illegal byte sequence it proceeds with the second patch.

I can make a PR to update the script in the repo if you want to.

https://gist.github.com/rjmolina13/4b46e5d0e8e4409bfc8aaff9c9cc4467

OR

#!/bin/bash
# discussion: https://github.com/JulienMaille/spicetify-dynamic-theme/issues/102
# script by: 
#   @Covkie
#   @JulienMaille
#   @rjmolina13

# Ensure Spicetify is in PATH
if ! command -v spicetify &> /dev/null; then
    echo -e "\033[31mError: spicetify not found. Ensure it is installed and available in your PATH.\033[0m"
    exit 1
fi

# Find where the Spotify binary is located
spotify_path=$(spicetify config spotify_path)

# Check for spicetify errors
if [[ $spotify_path == error* ]]; then
    echo -e "\033[31mFailed to patch the file. $spotify_path\033[0m"
    exit 1
fi

# Assemble the binary's path
if [[ "$OSTYPE" == "darwin"* ]]; then
    _spotify_path=$(dirname "$spotify_path")
    path="${_spotify_path}/MacOS/Spotify"
else
    path="${spotify_path}/spotify"
fi

# Validate the path to ensure it exists and is a file
if [[ ! -f "$path" ]]; then
    echo -e "\033[31mError: The Spotify binary was not found at the expected path: $path\033[0m"
    exit 1

fi

# Attempt to patch the binary with null bytes, and fallback to alternative patch if needed
if ! sed -i.bak 's/force-dark-mode/\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00/' "$path"; then
    echo -e "\033[31mEncountered illegal byte sequence. Attempting alternative patch.\033[0m"

    echo ""

    # Use alternative patch to replace 'force-dark-mode' with 'force-dark-nope'
    if LC_CTYPE=C sed -i.bak 's/force-dark-mode/force-dark-nope/' "$path"; then
        echo -e "\033[32mAlternative patch applied successfully.\033[0m"
    else
        echo -e "\033[31mFailed to apply alternative patch.\033[0m"
        exit 1
    fi
else
    echo -e "\033[32mPrimary patch applied successfully.\033[0m"
fi

echo -e "\033[32mThe patch is complete. You may now restart Spotify.\033[0m"