spicetify / cli

Command-line tool to customize Spotify client. Supports Windows, MacOS, and Linux.
https://spicetify.app
GNU Lesser General Public License v2.1
18.84k stars 735 forks source link

Spicetify WebNowPlaying.js extension not connecting to Rainmeter whilst WebNowPlaying companion for both firefox and chrome have no problem #983

Closed potatohub741 closed 3 years ago

potatohub741 commented 3 years ago

ℹ Computer information

📝 Provide detailed reproduction steps (if any)

  1. Install spotify version 1.1.62.583.gdac868ed-a and close window
  2. Create folder "Update" in %localappdata%\spotify and remove all groups in permissions
  3. Run "Invoke-WebRequest -UseBasicParsing "https://raw.githubusercontent.com/khanhas/spicetify-cli/master/install.ps1" | Invoke-Expression" in PowerShell window
  4. Run command "spicetify"
  5. Run command "spicetify backup apply enable-devtool"
  6. Close spotify
  7. Run command "spicetify config extensions webnowplaying.js"
  8. Run command "spicetify apply"
  9. Install latest version of rainmeter (beta) as well as the JaxCore3 skin and ModularPlayers skin
  10. Using the JaxCore3 settings, navigate to the ModularPlayers settings and switch "media" to Spotify (which uses the spicetify webnowplaying.js extension)

✔️ Expected result

ModularPlayers skin should display the currently playing spotify song and song information.

❌ Actual result

Plugin remains unchanged. NOTE 1: When webnowplaying chrome or firefox extension is used instead, the ModularPlayers skin works fine and displays the information correctly (including the web version of spotify) NOTE 2: I have tried other Rainmeter skins that utilise spicetify and its webnowplaying.js extension and they don't work either. NOTE 3: Using the dev tools in spotify, under the "sources" tab, under the "extensions" drop-down menu, webnowplaying.js is listed.

📷 Screenshots

image image image

Fosmos commented 3 years ago

Hmm the plugin still works for me. Have you checked the Rainmter Log while debug mode is on? I'm running this version of spotify: 1.1.66.578.gc54d0f69-a (which I think is the latest)

itsmeow commented 3 years ago

This is because the getProgress method has broken again. I've fixed it locally but there are also CSS mappings to update that Spicetify needs to work again.

potatohub741 commented 3 years ago

Hmm the plugin still works for me. Have you checked the Rainmter Log while debug mode is on? I'm running this version of spotify: 1.1.66.578.gc54d0f69-a (which I think is the latest)

Yeah I thought I might see something in the rainmeter logs, but there are no errors that I can see. image This is a log I just took of me opening spotify (spicetify), refreshing the ModularPlayers skin and pressing the play/pause button a couple times. I thought it might be a firewall issue, but I disabled my firewall and made exceptions for both spotify and rainmeter. I also thought there might be some server that spicetify or something has to communicate with that my ISP might be blocking, so I tried using mobile hotspot which didn't work either.

@itsmeow does the issue with the getProgress method mean that the skin fails to get all the song information? I'd understand if it at least had the song name, or the song cover, and just the progress meter was faulty, but literally nothing is displayed when spotify is playing a song. image

Fosmos commented 3 years ago

That's really odd because progress is working for me image

Try this skin: https://github.com/Fosmos/Simply. Right click it and head to it's settings menu and make sure you have Spotify (WebNowPlaying) selected

potatohub741 commented 3 years ago

@Fosmos I tried your skin, but with the webnowplaying mode selected it still doesn't work either : ( It is able to grab the song title and artist in the other spotify mode. In the webnowplaying mode the play/pause, skip forward/back dont work either (I assume they're coded through webnowplaying to communicate with webnowplaying in spicetify)

Fosmos commented 3 years ago

That's soooo weird. Everything (I mean everything) works perfectly for me. I can try your skin if you want. I'm literally stumped. One thing you can try is downloading the spiceitfy update's zip, extracting it and replacing everything in the spiceitfy-cli directory with everything in the expanded zip. Doubt it'll do anything, but 🤷🏻‍♂️ and then I guess while you're at it, double check you have webnowplaying.js properly set in the config file.

potatohub741 commented 3 years ago

I'm not 100% if this is the right link because the modular players skin was installed through another skin that manages skins called JaxCore. https://github.com/EnhancedJax/-JaxCore/releases/tag/v00030 This should be the link, but if not, then just look around the releases. You also have to install another thing called MagicMeter or something for modularplayers, but it should prompt you when you try to install modularplayers using JaxCore3.

Where could I find the spicetify update zip? And yeah I do have webnowplaying.js installed in spicetify. image I also just recently updated to spicetify v2.6.0 from the 2.5 meowpatch version which did nothing unfortunately : (

The funny thing is, it works perfectly fine when I use the webnowplaying extension in chrome or firefox. Even if I use the web version of spotify in those browsers. It's just the spotify client itself with spicetify that doesn't seem to link to webnowplaying in rainmeter.

Fosmos commented 3 years ago

https://github.com/khanhas/spicetify-cli/releases Here's where you get the latest

Fosmos commented 3 years ago

Also I was able to get one of the Jax skins to work image With the album cover too

potatohub741 commented 3 years ago

Do the other skin themes not work?

Fosmos commented 3 years ago

Yeah they all work image

potatohub741 commented 3 years ago

Are you running this version of spicetify? image

Fosmos commented 3 years ago

Yea I am, but I copied pasted the stuff from the zip, so my guess is they forgot to update the versioning

potatohub741 commented 3 years ago

Do you think any of this might be an issue if spicetify's webnowplay.js is looking for where rainmeter is installed? image

Fosmos commented 3 years ago

We have the same paths except for the ones with 'X'. Kinda doubt that would cause an issue specifically with webnowplaying though

uppercrust3 commented 3 years ago

I'm having the same issue as potatohub, and my visualizer is completely broken on both web player and desktop app.

potatohub741 commented 3 years ago

I have tried reinstalling spicetify again. Didn't work. I have tried uninstalling and reinstalling an older version of spotify (1.1.61.583.gad060c66-a). Didn't work. I have tried moving my rainmeter main install onto my primary hard drive. Didn't work I have tried uninstalling and reinstalling the rainmeter webnowplaying plugin. Didn't work.

For some reason, the chrome and firefox webnowplaying plugins work absolutely fine with rainmeter. I've really run out of ideas on how I can debug this.

The only thing I can think of right now is that maybe the playing data webnowplaying.js collects through spicetify is saved to some local folder somewhere, and spicetify/spotify doesn't have permissions to write to that folder, so when Rainmeter's webnowplaying plugin goes to grab that data, there's nothing there to grab. I assume if this was the case, then the chrome and firefox versions of webnowplaying save their data to a different folder, and therefore wouldn't run into the same issue. Does this sound plausible?

potatohub741 commented 3 years ago

image I looked at the spicetify devtools console and these errors were appearing. Could this have anything to do with spicetify not communicating with rainmeter?

Fosmos commented 3 years ago

Can you see where in the source code those problems are being hit?

potatohub741 commented 3 years ago

I'm not too experienced with java, html or css, but from browsing around the sources folders, I can't seem to find these Sourcemap files.

UltLight commented 3 years ago

I'm having the same problem, but cleartext and a skin I made seems to still work for me, anything other than those don't work.

potatohub741 commented 3 years ago

@UltimateLight I'm not sure if Cleartext uses webnowplaying does it? I believe it uses something like NowPlaying to grab the song title + artist, but can't do anything like grab song progress.

Would anyone happen to know where this "storage" variable is and whether it's local or some cloud storage? image image

I can't seem to find any webnowplaying variables in the storage folders above, but I'm pretty sure it's not the webnowplaying.js that's causing the issues because it should come up with this error if it fails to write to storage right? image

There are no other warnings associated with the webnowplaying.js that I can see. : (

potatohub741 commented 3 years ago

Update

I tried installing it on my laptop (which is running a beta version of windows 11). I did the exact same procedure I outlined above to install everything, and i was running spotify v1.1.60.672.g6ad9c215-a. and the 2.5.0 itsmeow patch of spicetify. It still did not work. I tried it on both my home internet connection and via hotspot, both of which didn't work. Help : ( NOTE: The Firefox webnowplaying extension works fine with ModularPlayers on my laptop

Fosmos commented 3 years ago

Ok what you can try is adding alerts (they're popups) around the code and seeing what values are being displayed.

  1. Open the js file in %USERPROFILE%/spicetify-cli/Extensions/webnowplaying.js
  2. Navigate to the end of function updateStorage()
  3. Add this line alert(storage.TITLE + " by " + storage.ARTIST)
  4. In a cmd do spicetify apply

If you don't see a popup then the code isn't making it there, so move up the alert (and you can put any string in there like "hi" or something) and keep moving up till something happens. If nothing happens then the problem may be outside of this script

potatohub741 commented 3 years ago

If I put the alert here, it pops up. image

If i put the alert here, it pops up. image

But here, nothing. image

If I put it here, nothing. image

It seems to just not go past that first if statement.

Fosmos commented 3 years ago

Hmm that well that makes sense why it doesn't working. Try breaking up the if statement it's entering (with the return) like this

if (!Spicetify.CosmosAsync) {
   setTimeout(WebNowPlaying, 500);
   alert("First if")
   return;
}

if (!Spicetify.Platform) {
   setTimeout(WebNowPlaying, 500);
  alert("Second if")
  return;
}
eetle commented 3 years ago

I'm having the same issue but I'm on windows 11, I'm running off Spotify 1.62 and spicetify 2.5.

eetle commented 3 years ago

I just downgraded form spicetify 2.5.0 patch 3 to spicetify version 2.5.0 and its works fine! must be any issue with new version? I was getting that "Cannot find symbol for Custom app React symbols" error when installing before, so the issue is probably connected

potatohub741 commented 3 years ago

How did you downgrade? @eetle Whenever I try to upgrade, and then run spicetify restore backup apply, it reverts back to 2.5.0 itsmeow patch.

And @Fosmos I tried running separate if statements like you said and both alerts pop up fine one after the other. But I added a third alert into the updateStorage(data) function, and it doesn't make it past the "Second if" alert. image

eetle commented 3 years ago

Here is a link to the download https://github.com/khanhas/spicetify-cli/releases/tag/v2.5.0.

I just downloaded the spicetify-2.5.0-windows-x64.zip and used these files to replace the v2.5 patch 3 ones in C:\Users\USERNAME\spicetify-cli

and then you treat it as a fresh install, just run the commands.

potatohub741 commented 3 years ago

I downgraded to 2.5.0 and unfortunately it's still not working.

potatohub741 commented 3 years ago

UPDATE:

I commented out the return line within the first if statement, and the player works fine except for the fact that it doesn't show the album art. image image

Buttons on the player work fine as well as using the progress bar to skip to different points in the song.

image

This bit of code that I think updates the cover image also doesn't show this alert even when I switch songs and such.

Fosmos commented 3 years ago

I think what that last bit of code means is that it's getting an index different then -1, which either means it found a cached album cover or indexOf is returning an error that's not -1. Try changing the equals operator to <= (I'm not sure if you can do <== or something like that)

potatohub741 commented 3 years ago

I gave that a go, and when looking at the dev tools console in spotify, I can now see this error. image

Points to this line: image

Is sp://... a local storage space or some network connection? Just as I was typing this, I got more error messages. image Leading to these lines: image

Fosmos commented 3 years ago

Hmm interesting. I feel like the whole caching system isn't working great right now. So maybe comment out line 49?

potatohub741 commented 3 years ago

Does that mean I won't be able to get the album art working for the rainmeter skin?

Fosmos commented 3 years ago

Not sure actually. The js usually gets the link to the album art which is basically a request to Spotify's servers, then it downloads it. Sometime ago I was trying to figure out how to get album art to work when Spotify was offline but couldn't so I don't think it's caching right now anyways

potatohub741 commented 3 years ago

I imagine that webnowplaying.js in spicetify just copies/retrieves the album art from spotify's cache after spotify itself downloaded all the song data for the current playing song. So if spotify is fine with grabbing the album art, there must be something wrong with how webnowplaying.js grabs that data from spicetify. It looks like the script opens something called a WebSocket (I have no idea what it is tbh) and tries to store the album art in that location, but can't access that location (which you can sort of see in the errors in the images I sent before). Could it maybe be some sort of network blocking issue on my end?

Fosmos commented 3 years ago

I don't think it actually does. Unless it's changed since the last time I tried, when your computer is offline and you have downloaded music, Spotify shows the art just fine, but webnowplaying doesn't seem to be able to get it. Now I may be doing things wrong but from my quick investigating some time ago this is what I found

potatohub741 commented 3 years ago

It is very weird how it seems like it's just me (or only a few people) who are experiencing this problem, but thank you for your help! The alert() thing really helped me find where the code was stopping so I could comment it out, which seems to be a good bandaid fix for now.

Fosmos commented 3 years ago

Version 2.6.1 was just released. It doesn't touch webnowplaying.js but who knows maybe it'll fix something 🤷🏻‍♂️

TheGeeKing commented 3 years ago

Spicetify 2.6.1 is just a first fix for Spotify 1.1.66 and later, for extensions and custom apps. I would suggest to stay on 2.6 as the Ui is buggy with 2.6.1 extensions and custom apps

GrandArc commented 3 years ago

It is very weird how it seems like it's just me (or only a few people) who are experiencing this problem, but thank you for your help! The alert() thing really helped me find where the code was stopping so I could comment it out, which seems to be a good bandaid fix for now.

I actually have the same problem, my Rainmeter WebNowPlaying hasn't been working for a while and only today I tried to find the fix for the issue again. I had the exact same issue where the code couldn't get past if (!Spicetify.CosmosAsync || !Spicetify.Platform).

Used your band-aid idea to comment out the return function. It worked now, but like you said, the album art wouldn't appear on the Rainmeter skin which makes it much uglier than it usually look like :(

Eden333 commented 3 years ago

It is very weird how it seems like it's just me (or only a few people) who are experiencing this problem, but thank you for your help! The alert() thing really helped me find where the code was stopping so I could comment it out, which seems to be a good bandaid fix for now.

I actually have the same problem, my Rainmeter WebNowPlaying hasn't been working for a while and only today I tried to find the fix for the issue again. I had the exact same issue where the code couldn't get past if (!Spicetify.CosmosAsync || !Spicetify.Platform).

Used your band-aid idea to comment out the return function. It worked now, but like you said, the album art wouldn't appear on the Rainmeter skin which makes it much uglier than it usually look like :(

same here, I commented out the first return, and it would work, besides not loading the cover. I had the patch4 thingy from someone who had linked it, idk if that matters.

TheSolly commented 3 years ago

Thanks @potatohub741 for pointing the issue and your effort to fix, I had the same issue and was looking for a solution... I've build upon you work and found the culprit. Which was that Spicetify object doesnt have a Platform method anymore! That caused the whole Module to break! I've modified the webnowplaying.js to fix this issue, at least for now. The below is working now with latest spotify and spicetify and ModularPlayer skin

// NAME: WebNowPlaying Companion
// AUTHOR: khanhas (based on https://github.com/tjhrulz/WebNowPlaying-BrowserExtension)
// DESCRIPTION: Get song information and control player

/// <reference path="../globals.d.ts" />

(function WebNowPlaying() {
  // removed the Spicetify.Platform check as Spicetify doesnt contain a Platform method anymore!
  if (!Spicetify.CosmosAsync) {
    setTimeout(WebNowPlaying, 500);
    return;
  }

  let currentMusicInfo;
  let ws;
  let currState = 0;
  const storage = {};
  function updateStorage(data) {
    if (!data?.track?.metadata) {
      return;
    }
    const meta = data.track.metadata;
    storage.TITLE = meta.title;
    storage.ALBUM = meta.album_title;
    storage.DURATION = convertTimeToString(parseInt(meta.duration));
    storage.STATE = !data.is_paused ? 1 : 2;
    storage.REPEAT = data.options.repeating_track
      ? 2
      : data.options.repeating_context
      ? 1
      : 0;
    storage.SHUFFLE = data.options.shuffling_context ? 1 : 0;
    storage.ARTIST = meta.artist_name;
    let artistCount = 1;
    while (meta["artist_name:" + artistCount]) {
      storage.ARTIST += ", " + meta["artist_name:" + artistCount];
      artistCount++;
    }
    if (!storage.ARTIST) {
      storage.ARTIST = meta.album_title; // Podcast
    }
    // Spicetify doesnt contain a Platform method anymore!
    // Spicetify.Platform?.LibraryAPI.contains(data.track.uri).then(
    //   ([added]) => (storage.RATING = added ? 5 : 0)
    // );

    const cover = meta.image_xlarge_url;
    if (cover?.indexOf("localfile") === -1) {
      storage.COVER =
        "https://i.scdn.co/image/" +
        cover.substring(cover.lastIndexOf(":") + 1);
    } else {
      storage.COVER = "";
    }
  }

  Spicetify.CosmosAsync.sub("sp://player/v2/main", updateStorage);

  function updateInfo() {
    if (!Spicetify.Player.data && currState !== 0) {
      ws.send("STATE:" + 0);
      currState = 0;
      return;
    }

    storage.POSITION = convertTimeToString(Spicetify.Player.getProgress());
    storage.VOLUME = Math.round(Spicetify.Player.getVolume() * 100);

    for (const field in storage) {
      try {
        const data = storage[field];
        if (data !== undefined && currentMusicInfo[field] !== data) {
          ws.send(`${field}:${data}`);
          currentMusicInfo[field] = data;
        }
      } catch (e) {
        ws.send(`Error:Error updating ${field} for Spotify Desktop`);
        ws.send("ErrorD:" + e);
      }
    }
  }

  function fireEvent(event) {
    const m = event.data;
    const n = m.indexOf(" ");
    let type = n === -1 ? m : m.substring(0, n);
    type = type.toUpperCase();
    const info = m.substring(n + 1);

    switch (type) {
      case "PLAYPAUSE":
        Spicetify.Player.togglePlay();
        break;
      case "NEXT":
        Spicetify.Player.next();
        break;
      case "PREVIOUS":
        Spicetify.Player.back();
        break;
      case "SETPOSITION":
        Spicetify.Player.seek(parseInt(info) * 1000);
        break;
      case "SETVOLUME":
        Spicetify.Player.setVolume(parseInt(info) / 100);
        break;
      case "REPEAT":
        Spicetify.Player.toggleRepeat();
        break;
      case "SHUFFLE":
        Spicetify.Player.toggleShuffle();
        break;
      case "RATING":
        const like = parseInt(info) > 3;
        const isLiked = storage.RATING > 3;
        if ((like && !isLiked) || (!like && isLiked)) {
          Spicetify.Player.toggleHeart();
        }
        break;
      case "TOGGLETHUMBSUP":
        if (!(storage.RATING > 3)) {
          Spicetify.Player.toggleHeart();
        }
        break;
      case "TOGGLETHUMBSDOWN":
        if (storage.RATING > 3) {
          Spicetify.Player.toggleHeart();
        }
        break;
    }
  }

  (function init() {
    ws = new WebSocket("ws://127.0.0.1:8974/");
    let sendData;

    ws.onopen = () => {
      ws.send("PLAYER: Spotify Desktop");
      currState = 1;
      currentMusicInfo = {};
      sendData = setInterval(updateInfo, 500);
    };

    ws.onclose = () => {
      clearInterval(sendData);
      setTimeout(init, 2000);
    };

    ws.onmessage = fireEvent;
  })();

  window.onbeforeunload = () => {
    ws.onclose = null; // disable onclose handler first
    ws.close();
  };

  /**
   * Zero padding a number
   * @param {number} number number to pad
   * @param {number} length
   */
  function pad(number, length) {
    var str = String(number);
    while (str.length < length) {
      str = "0" + str;
    }
    return str;
  }

  /**
   * Convert seconds to a time string acceptable to Rainmeter
   * @param {number} timeInMs
   * @returns {string}
   */
  function convertTimeToString(timeInMs) {
    const seconds = Math.round(timeInMs / 1000);
    const minutes = Math.floor(seconds / 60);
    if (minutes < 60) {
      return `${minutes}:${pad(seconds % 60, 2)}`;
    }
    return `${Math.floor(minutes / 60)}:${pad(minutes % 60, 2)}:${pad(
      seconds % 60,
      2
    )}`;
  }
})();
GrandArc commented 3 years ago

Can confirm the code above works! Thank you very much!! :)

itsmeow commented 3 years ago

@TheSolly The Platform hook has broken, I'm working on reimplementing it but the entire format changed again.

TheSolly commented 3 years ago

@itsmeow make sense now, thanks for letting us know! Let me know if i could be of any help 🙏

potatohub741 commented 3 years ago

I just tried your fix, and I'm glad to say it worked perfectly! Thanks for everyone's help!

Eden333 commented 3 years ago

Works again!