Skip to content

Commit

Permalink
Merge pull request #75 from Fabrizz/dev-features
Browse files Browse the repository at this point in the history
Dev features
  • Loading branch information
Fabrizz authored Nov 25, 2024
2 parents 77af57c + a42808e commit d5f4532
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 19 deletions.
12 changes: 10 additions & 2 deletions MMM-OnSpotify.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ Module.register("MMM-OnSpotify", {
ONSPOTIFY_HIDE: "ONSPOTIFY_HIDE",
},

// Allow config with or without
// Allow config with or without subdivition
isPlaying: 1,
isEmpty: 2,
isPlayingHidden: 1,
Expand Down Expand Up @@ -135,10 +135,15 @@ Module.register("MMM-OnSpotify", {
experimentalCanvasEffect: "cover",
// Add the album cover inside the canvas
experimentalCanvasAlbumOverlay: true,
experimentalCanvasSPDCookie: "",

// In special use cases where a frontend needs to take over other you can disabl
// the id matching for the frontend, so "multiple" frontends can talk to the module even if not supported
matchBackendUUID: false,

// Send a notification with the color data when only when the song changes, this is useful for modules
// that are not going to show the color inside the dom.
experimentalColorSignaling: false,
},

start: function () {
Expand Down Expand Up @@ -199,6 +204,8 @@ Module.register("MMM-OnSpotify", {
version: this.version,
},
(a, b) => this.translate(a, b),
(a, b) => this.sendNotification(a, b), // This is not the best as I would like this logic to be separated from the,
// DomBuilder but I dont have time to refractor everything. Solves #81 issue
);

/* Future update:
Expand Down Expand Up @@ -685,13 +692,14 @@ Module.register("MMM-OnSpotify", {
userAffinityUseTracks: this.config.userAffinityUseTracks,
deviceFilter: this.config.deviceFilter,
deviceFilterExclude: this.config.deviceFilterExclude,
useCanvas: this.config.experimentalCanvas
useCanvas: this.config.experimentalCanvas,
},
credentials: {
clientId: this.config.clientID,
clientSecret: this.config.clientSecret,
accessToken: this.config.accessToken,
refreshToken: this.config.refreshToken,
experimentalCanvasSPDCookie: this.config.experimentalCanvasSPDCookie,
},
language: this.config.language,
backendExpectId: this.backendExpectId,
Expand Down
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ The module includes an Authentication Service that guide you through the configu
> [!NOTE]
> All the data stays in your mirror. If you have multiple mirrors, the Authentication Service guides you on creating a new Spotify App per mirror.

https://github.com/Fabrizz/MMM-OnSpotify/assets/65259076/5d78672e-8feb-45de-92f4-ed44f0771432

https://github.com/Fabrizz/MMM-OnSpotify/assets/65259076/f7c0928f-3806-48ba-a813-87962dd9ea8b

> This module shows what is on your Spotify Connect. if you want to use Spotify in your mirror you should look at [Raspotify](https://github.com/dtcooper/raspotify)
# Installation
### Step 1: Clone the module and install dependencies
Expand Down Expand Up @@ -91,6 +91,7 @@ Once you finish, you are all set with the basic configuration. Scroll down to se
experimentalCanvas: false,
experimentalCanvasEffect: 'cover',
experimentalCanvasAlbumOverlay: false,
experimentalCanvasSPDCookie: "",
// Theming General
roundMediaCorners: true,
roundProgressBar: true,
Expand All @@ -103,6 +104,7 @@ Once you finish, you are all set with the basic configuration. Scroll down to se
blurCorrectionInAllSides: false,
alwaysUseDefaultDeviceIcon: false,
experimentalCSSOverridesForMM2: false, // [SEE BELOW]
experimentalColorSignaling: false,
},
},
```
Expand Down Expand Up @@ -177,11 +179,18 @@ experimentalCSSOverridesForMM2: [
| spotifyCodeExperimentalSeparateItem <br> `true` | Separates or joins the Spotify Code Bar to the cover art. Also respects `roundMediaCorners` and `spotifyCodeExperimentalUseColor`. <br /><br /><img alt="Spotify code bar separation" src=".github/content/readme/banner-codeseparation.png" aling="left" height="100"> |

#### Canvas
> [!IMPORTANT]
> EXPERIMENTAL - Using this without auth will get this funtion rate-limited. For that you can add a `experimentalCanvasSPDCookie`. This is more advanced as it requieres you to get the cookie from a Spotify Web session. Not recommended for all users.
> [!CAUTION]
> Canvases are an internal implementation by the Spotify team and its not available in the web API. Use at your own discretion, personal usage only.
| Key | Description |
| :-- | :-- |
| experimentalCanvas <br> `false` | Shows the Spotify Canvas if available. This is an experimental feature, as this API is not documented and private. |
| experimentalCanvasEffect <br> `cover` | Control how is the canvas is going to be displayed. Options are: <br />- `cover`: The Canvas is clipped to have the same height as the album cover. Recommended for low-power devices and if the module is not in a `bottom_*` position. <br />- `scale`: Scale up/down the module to fit the entire Canvas without clipping it. <br /> |
| experimentalCanvasAlbumOverlay <br> `true` | Show the cover art inside the Spotify Canvas. |
| experimentalCanvasEffect <br> `cover` | Control how is the canvas is going to be displayed. Options are: <br />- `cover`: The Canvas is clipped to have the same height as the album cover. Recommended for low-power devices and if the module is not in a `bottom_*` position. <br />- `scale`: Scale up/down the module to fit the entire Canvas without clipping it. <br /> |
| experimentalCanvasSPDCookie <br> `""` | Adds the SPD cookie from a web Spotify session to stop Spotify from returning a 500 error. Spotify could decide also to just send a 500 error depending on the user agents and other factors, this just affects the module. Still, this feature is optional and this API is NOT public. You can search "Extract Spotify SPD cookie" in youtube/other to learn how to do this. **DO NOT** share this cookie!. |

#### General Theming options
| Key | Description |
Expand All @@ -197,6 +206,7 @@ experimentalCSSOverridesForMM2: [
| blurCorrectionInAllSides <br> `false` | Same as `blurCorrectionInFrameSide`, but applies the correction on all of the borders for a more subtle effect. |
| alwaysUseDefaultDeviceIcon <br> `false` | The device icon changes depending on the player type. If you don’t like this behaviour you can disable it. |
| experimentalCSSOverridesForMM2 <br> `false` | An array containing CSS overrides, OnSpotify manages the status depending on what is displayed on the screen and lets you customize other modules. [See above](#theming-3rd-party-modules) |
| experimentalColorSignaling <br> `false` | Sends a notification with the color data for modules that are not DOM based and need the color when its already processed. |

> See also: [Disabling **all** color based theming](#other)
Expand All @@ -223,6 +233,7 @@ Control your mirror (and other modules) using Apple Homekit protocol! (Also comp
| key | Description |
| :-- | :-- |
| `THEME_PREFERENCE` | ↑ Sent to signal other modules that color data is available. |
| `INSTANT_COLOR` | ↑ Sent to signal other modules that color data has been updated instantly, also sends the raw vibrant data, only when `experimentalColorSignaling` is turned on. |
| `NOW_PLAYING` | ↑ When the player state changes, the module sends a notification so other modules can, for example, [show lyrics](#lyrics). |
| `DEVICE_CHANGE` | ↑ Everytime the Spotify Connect target changes, this notification is fired. |
| `ONSPOTIFY_NOTICE` | ↑ This notification signals other modules that OnSpotify is available. |
Expand Down Expand Up @@ -267,5 +278,7 @@ You cannot migrate from NowPlayingInSpotify, as the scopes included in the NPOS

- Contributions wanted! Add features or your language using `translations/yourLanguage.json`. Currently we have translations for: Spanish, English, German

- You can custom CSS and functions in the "Issues" tab. For example https://github.com/Fabrizz/MMM-OnSpotify/issues/65 for changing the size and hiding other modules using ONSP state.

With <3 by Fabrizio | [fabriz.co](https://fabriz.co/) | Star this repository!
[<img alt="Fabrizz logo" src=".github/content/readme/logo-fabrizz-fill.png" width="200" align="right">](https://fabriz.co/)
4 changes: 2 additions & 2 deletions auth/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -242,8 +242,8 @@ <h4 class="card-header py-3">Step 3: Configure your mirror</h4>
clientID: <span style="color: rgb(242, 210, 152);">"{{clientID}}"</span>,
clientSecret: <span style="color: rgb(242, 210, 152);">"{{clientSecret}}"</span>,
accessToken: <span style="color: rgb(242, 210, 152);">"{{accessToken}}"</span>,
refreshToken: <span style="color: rgb(242, 210, 152);">"{{refreshToken}}"</span>
<span style="color: rgba(255, 255, 255, 0.48);">/* Add here your theming and behaviour configurations */</span>
refreshToken: <span style="color: rgb(242, 210, 152);">"{{refreshToken}}"</span>,
<span style="color: rgba(255, 255, 255, 0.48);">/* Add here your configurations */</span>
}
},</pre>

Expand Down
2 changes: 1 addition & 1 deletion node_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ module.exports = NodeHelper.create({
try {
// use then to prevent context issue
this.fetcher.getCanvas(uri).then(canvas => {
console.log("[CANVAS DATA]", JSON.stringify(canvas), typeof x)
// console.log("[CANVAS DATA]", JSON.stringify(canvas))

if (canvas.canvasesList.length == 1 && canvas.canvasesList[0].canvasUrl.endsWith('.mp4')) {
const item = canvas.canvasesList[0];
Expand Down
24 changes: 16 additions & 8 deletions utils/SpotifyDomBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@
/* eslint-disable no-undef */

class SpotifyDomBuilder {
constructor(pathPrefix, config, other, translator) {
constructor(pathPrefix, config, other, translator, externalNotifier) {
this.pathPrefix = pathPrefix;
this.config = { ...config, ...other };
this.translate = translator;
this.notifyModules = externalNotifier;
this.root = document.querySelector(":root");
this.firstUpdate = true;
this.lastItemURI = null;
Expand Down Expand Up @@ -610,7 +611,6 @@ class SpotifyDomBuilder {
}

updateCanvas(data) {
console.log("SYNC", data)
const container = document.getElementById("VSNO-TARGET-SWAPPABLE");
this.coverData = data;
if (container == null) return;
Expand Down Expand Up @@ -767,12 +767,10 @@ class SpotifyDomBuilder {

/* Image color processing */
async setGlobalColors(url, data) {
const ch = url !== this.lastUrlProcessed ? "" : "[PALETTE CACHED] | ";
const shouldUpdatePalette = url !== this.lastUrlProcessed;

this.firstUpdate = false;
const palette =
url !== this.lastUrlProcessed
? await this.getVibrant(url)
: this.lastPalette;
const palette = shouldUpdatePalette ? await this.getVibrant(url) : this.lastPalette;

if (!palette) return;
this.lastPalette = palette;
Expand All @@ -785,6 +783,16 @@ class SpotifyDomBuilder {
);
}

// Notify external modules about the color change instantly after the color is set
// Added to fix/help #81
if (this.config.experimentalColorSignaling)
this.notifyModules("INSTANT_COLOR", {
vibrantRawOutput: palette,
isCacheedPalette: !shouldUpdatePalette,
forUrl: url,
})


// Fix color data using RGB_Linear_Shade to get more contrast
// This is used in the SpotifyCode bar, if enabled with useColorInProgressBar
// its also used there for continuity
Expand Down Expand Up @@ -873,7 +881,7 @@ class SpotifyDomBuilder {
(Brightness_By_Color(palette.Vibrant.hex) / 255) * 100,
)}%`
: ""
} | ${ch}${data.itemName} | ${url}`,
} | ${shouldUpdatePalette ? "" : "[PALETTE CACHED] | "}${data.itemName} | ${url}`,
`padding:0.7em;border-radius:3em;background-color:${palette.Vibrant.hex}`,
`padding:0.7em;border-radius:3em;margin-left:0.3em;background-color:${palette.LightVibrant.hex};color:${palette.DarkVibrant.hex}`,
`padding:0.7em;border-radius:3em;margin-left:0.3em;background-color:${palette.DarkVibrant.hex};color:${palette.LightVibrant.hex}`,
Expand Down
28 changes: 26 additions & 2 deletions utils/SpotifyFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ module.exports = class SpotifyFetcher {
"\x1b[0m[\x1b[35mMMM-OnSpotify\x1b[0m] Refresh access token >> \x1b[41m\x1b[37m CODE 429 \x1b[0m %s",
"You are being rate limited by Spotify (429). Use only one SpotifyApp per module/implementation",
);
if (res.status !== 200) {
console.warn(
`\x1b[0m[\x1b[35mMMM-OnSpotify\x1b[0m] Refresh access token >> \x1b[41m\x1b[37m CODE ${res.status} \x1b[0m %s`,
"Error refreshing access token. Check your credentials, account type or status.",
);
return new Error("Error refreshing access token")
}

return res.json();
})
.catch((error) => {
Expand Down Expand Up @@ -239,7 +247,7 @@ module.exports = class SpotifyFetcher {
'accept': 'application/protobuf',
'content-type': 'application/x-www-form-urlencoded',
'accept-language': 'en',
'user-agent': 'Spotify/8.5.49 iOS/Version 13.3.1 (Build 17D50)',
'user-agent': 'Spotify/8.6.98 iOS/15.3.1',
'accept-encoding': 'gzip, deflate, br',
'authorization': `Bearer ${this.canvasToken}`,
},
Expand Down Expand Up @@ -270,7 +278,23 @@ module.exports = class SpotifyFetcher {
if (currentTime < this.canvasTokenExpiresAt) {
return this.canvasToken
} else {
return fetch(new URL("get_access_token?reason=transport&productType=web_player", spotifyBase))
let ccc = {
headers: {
//"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/114.0",
//Accept:
// "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
//"Accept-Language": "en-US,en;q=0.5",
//"Alt-Used": "open.spotify.com",
//"Upgrade-Insecure-Requests": "1",
//"Sec-Fetch-Dest": "document",
//"Sec-Fetch-Mode": "navigate",
//"Sec-Fetch-Site": "cross-site",
}
}
if (this.credentials.experimentalCanvasSPDCookie.length > 0) {
ccc.headers.Cookie = `sp_dc=${this.credentials.experimentalCanvasSPDCookie}`;
}
return fetch(new URL("get_access_token?reason=transport&productType=web_player", spotifyBase), ccc)
.then(async res => {
if (!res.ok && res.status === 429)
console.warn(
Expand Down
3 changes: 1 addition & 2 deletions utils/canvas/readme.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
## Experimental canvas implementation
Original:
* https://github.com/Vibrant-Colors/node-vibrant

* https://github.com/bartleyg/my-spotify-canvas
Implementation:
* https://github.com/dientuki
* https://github.com/Fabrizz/MMM-OnSpotify/issues/66
Expand Down

0 comments on commit d5f4532

Please sign in to comment.