From b688553899fa0de7b15756323ec5d607608117e7 Mon Sep 17 00:00:00 2001 From: Fabrizio <65259076+Fabrizz@users.noreply.github.com> Date: Sun, 25 Feb 2024 02:03:52 -0300 Subject: [PATCH] V4.0.0 General update --- MMM-OnSpotify.js | 66 +++++++++++-------- README.md | 49 +++++++++----- auth/client/assets/clientLogic.js | 4 +- auth/client/index.html | 44 +++++++------ css/included.css | 8 +++ node_helper.js | 37 +++++++++-- package.json | 8 +-- translations/de.json | 3 +- translations/en.json | 5 +- translations/es.json | 3 +- .../{yourlanguaje.json => yourLanguage.json} | 5 +- utils/SpotifyDomBuilder.js | 37 ++++++----- utils/SpotifyFetcher.js | 26 +++++--- 13 files changed, 185 insertions(+), 110 deletions(-) rename translations/{yourlanguaje.json => yourLanguage.json} (87%) diff --git a/MMM-OnSpotify.js b/MMM-OnSpotify.js index 18a55b5..842fefb 100644 --- a/MMM-OnSpotify.js +++ b/MMM-OnSpotify.js @@ -25,7 +25,7 @@ Module.register("MMM-OnSpotify", { prefersLargeImageSize: false, // If you selected a high interval, you can hide the progress timestamp // and animate the seekbar to the timing of the updateInterval, making it look better. - hideTrackLenghtAndAnimateProgress: false, + hideTrackLengthAndAnimateProgress: false, // Shows the Vibrant output in the console as a palette and color data. showDebugPalette: false, // Max age in seconds for personal data. If set to 0 they update when the player changes @@ -136,6 +136,8 @@ Module.register("MMM-OnSpotify", { this.nowDisplaying = null; this.globalThemeSelected = null; this.currentStatus = ""; + this.backendExpectId = Date.now().toString(16); + this.lastServerId = undefined; this.retries = 0; this.lastPrivate = [null, null]; this.lastStatus = "isPlaying"; @@ -145,7 +147,7 @@ Module.register("MMM-OnSpotify", { typeof this.config.theming.experimentalCSSOverridesForMM2 === "object"; //////////////////////////////////////////////////////////////////////////////////////////// - this.version = "3.3.1"; + this.version = "4.0.0"; //////////////////////////////////////////////////////////////////////////////////////////// this.displayUser = @@ -195,20 +197,7 @@ Module.register("MMM-OnSpotify", { this.root = document.querySelector(":root"); - this.sendSocketNotification("SET_CREDENTIALS_REFRESH", { - preferences: { - userAffinityUseTracks: this.config.userAffinityUseTracks, - deviceFilter: this.config.deviceFilter, - deviceFilterExclude: this.config.deviceFilterExclude, - }, - credentials: { - clientId: this.config.clientID, - clientSecret: this.config.clientSecret, - accessToken: this.config.accessToken, - refreshToken: this.config.refreshToken, - }, - language: this.config.language, - }); + this.sendCredentialsBackend(); this.updateFetchingLoop(this.config.updateInterval[this.lastStatus]); }, @@ -267,9 +256,6 @@ Module.register("MMM-OnSpotify", { }, getScripts: function () { let files = [ - this.file( - "node_modules/moment-duration-format/lib/moment-duration-format.js", - ), this.file("utils/SpotifyDomBuilder.js"), // Use a custom build of the "node-vibrant" library that fixes the webworker usage this.file("vendor/vibrant.worker.min.js"), @@ -284,11 +270,6 @@ Module.register("MMM-OnSpotify", { ) files.push(this.file("node_modules/dompurify/dist/purify.min.js")); - // Only load moment if for some reason MM2 has not loaded it yet, fixes https://github.com/Fabrizz/MMM-OnSpotify/issues/32 - // Actually https://github.com/Fabrizz/MMM-OnSpotify/pull/33 fixed it. - if (!("moment" in window)) { - files.push(this.file("node_modules/moment/min/moment.min.js")); - } return files; }, getTranslations: function () { @@ -406,6 +387,19 @@ Module.register("MMM-OnSpotify", { this.isConnectedToSpotify = false; this.smartUpdate("PLAYER_DATA"); break; + case "REQUEST_REAUTH": + if (this.lastServerId === payload) break; + this.lastServerId = payload; + console.warn( + `%c· MMM-OnSpotify %c %c[WARN]%c ${this.translate("BACKEND_REAUTH")}`, + "background-color:#84CC16;color:black;border-radius:0.4em", + "", + "background-color:orange;color:black;", + "", + ); + this.sendNotification("SERVERSIDE_RESTART"); + this.sendCredentialsBackend(); + break; } }, notificationReceived: function (notification, payload) { @@ -501,12 +495,13 @@ Module.register("MMM-OnSpotify", { }, instantUpdate: function () { - this.sendSocketNotification("REFRESH_PLAYER"); + this.sendSocketNotification("REFRESH_PLAYER", this.backendExpectId); // To prevent multiple api calls, the call is requested but its only called // here, following the interval of the player. - if (this.requestUserData) this.sendSocketNotification("REFRESH_USER"); + if (this.requestUserData) + this.sendSocketNotification("REFRESH_USER", this.backendExpectId); if (this.requestAffinityData) - this.sendSocketNotification("REFRESH_AFFINITY"); + this.sendSocketNotification("REFRESH_AFFINITY", this.backendExpectId); }, smartUpdate: function (type) { @@ -624,6 +619,23 @@ Module.register("MMM-OnSpotify", { getImage: (im, prefersLarge) => im ? (prefersLarge ? im.large : im.medium) : null, + sendCredentialsBackend() { + this.sendSocketNotification("SET_CREDENTIALS_REFRESH", { + preferences: { + userAffinityUseTracks: this.config.userAffinityUseTracks, + deviceFilter: this.config.deviceFilter, + deviceFilterExclude: this.config.deviceFilterExclude, + }, + credentials: { + clientId: this.config.clientID, + clientSecret: this.config.clientSecret, + accessToken: this.config.accessToken, + refreshToken: this.config.refreshToken, + }, + language: this.config.language, + backendExpectId: this.backendExpectId, + }); + }, logBadge: function () { console.log( ` ⠖ %c by Fabrizz %c ${this.name}`, diff --git a/README.md b/README.md index 7976126..e3fec73 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ npm run auth ``` Once you finish, you are all set with the basic configuration. Scroll down to see all the different theming options for the module. -> When the Authorization Service is running, you can access it from your Raspberry Pi going to `http://localhost:8100/`. You can also access it remotely using `http://:8100/`. Note that using the device where you have Magic Mirror is recommended, as you are going to copy and paste the generated config entry. +> When the Authorization Service is running, you can access it from your Raspberry Pi going to `http://localhost:8100/`. You can also access it remotely using `http://:8100/`. Note that using the device where you have MagicMirror² installed is recommended, as you are going to copy and paste the generated config entry. # Module Configuration #### The configuration section is divided in groups, scroll down or click what to see below: @@ -59,7 +59,7 @@ Once you finish, you are all set with the basic configuration. Scroll down to se displayWhenEmpty: "both", userAffinityUseTracks: false, prefersLargeImageSize: false, - hideTrackLenghtAndAnimateProgress: false, + hideTrackLengthAndAnimateProgress: false, showDebugPalette: false, userDataMaxAge: 14400, userAffinityMaxAge: 36000, @@ -77,8 +77,10 @@ Once you finish, you are all set with the basic configuration. Scroll down to se // Animations [SEE BELOW] mediaAnimations: false, fadeAnimations: false, + scrollAnimations: false, textAnimations: true, transitionAnimations: true, + spotifyVectorAnimations: false, // Spotify Code (EXPERMIENTAL) spotifyCodeExperimentalShow: true, spotifyCodeExperimentalUseColor: true, @@ -123,7 +125,7 @@ experimentalCSSOverridesForMM2: [ | displayWhenEmpty
`"both"` | What to display when the player is empty. Options are:
- `user`: Displays user card
- `affinity`: Shows user top albums/songs
- `both`: Combines the user card and affinity data
- `logo`: Displays the Spotify logo
- `none`: Display only when playing

Display when empty | | userAffinityUseTracks
`false` | If you have selected to show your affinity data on idle, you can choose between showing tracks or albums. | | prefersLargeImageSize
`false` | If you prefer to use higher resolution images. Not recommended for normal use. | -| hideTrackLenghtAndAnimateProgress
`false` | Depending on your internet conection or your selected polling rate, you may want to hide the actual seconds and animate the progress bar. | +| hideTrackLengthAndAnimateProgress
`false` | Depending on your internet conection or your selected polling rate, you may want to hide the actual seconds and animate the progress bar. | | showDebugPalette
`false` | Shows the Vibrant output as a palette in the web console.

Debug palette | | userDataMaxAge
`14400` | (Seconds) The time in seconds of user data TTL. If set to 0, its updated everytime that the player goes to idle, as user data rarely changes, this allows a middle ground between updating always and only on boot | | userAffinityMaxAge
`36000` | (Seconds) The time in seconds of affinity data TTL. If set to 0, its updated everytime that the player goes to idle, as user data rarely changes, this allows a middle ground between updating always and only on boot | @@ -151,17 +153,26 @@ experimentalCSSOverridesForMM2: [ > - If you are using a **RPI3** or below, I recommend turning off the animations and the blurred background, as its GPU intensive. > - If you using a **higher power device** (**RPI5**), you can turn on all the animations, the fade, text and transition animations look really good! +#### Animations | Key | Description | | :-- | :-- | -| spotifyCodeExperimentalShow
`true` | Shows the Spotify Code (SpotifyScannable) for the current Song/Podcast/Audiobook. This is an experimental feature, as the API is not documented. SVG elements from the Spotify CDN are sanitized and parsed to allow animations (`spotifyVectorAnimations`).

Spotify code | -| spotifyCodeExperimentalUseColor
`true` | As shown on the image above, color the Spotify Code bar using cover art colors. | -| spotifyCodeExperimentalSeparateItem
`true` | Separates or joins the Spotify Code Bar to the cover art. Also respects `roundMediaCorners` and `spotifyCodeExperimentalUseColor`.

Spotify code bar separation | | mediaAnimations
`false` | Control the cover crossfade, this animation type waits for the image to be dowmloaded to do the fade between new/old media. (See the warning for RPIs above) | | fadeAnimations
`false` | Controls the fade effects between module status changes. Not too GPU intensive. (See the warning for RPIs above) | | scrollAnimations
`false` | Controls text scrolling for long music/podcast names/artist/show. (See the warning for RPIs above) | -| transitionAnimations
`true` | Controls the transition between color changes, GPU intensive, but looks really good. (See the warning for RPIs above) (It also affects other modules if you are using `experimentalCSSOverridesForMM2` default CSS config.) | | textAnimations
`true` | Control the animation of text on music/podcast change, also affects the "current device" text. (See the warning for RPIs above) | +| transitionAnimations
`true` | Controls the transition between color changes, GPU intensive, but looks really good. (See the warning for RPIs above) (It also affects other modules if you are using `experimentalCSSOverridesForMM2` default CSS config.) | | spotifyVectorAnimations
`false` | Control the animation of the Spotify code, It look really good, as it transitions seamless. (See the warning for RPIs above) | + +#### Spotify Code +| Key | Description | +| :-- | :-- | +| spotifyCodeExperimentalShow
`true` | Shows the Spotify Code (SpotifyScannable) for the current Song/Podcast/Audiobook. This is an experimental feature, as the API is not documented. SVG elements from the Spotify CDN are sanitized and parsed to allow animations (`spotifyVectorAnimations`).

Spotify code | +| spotifyCodeExperimentalUseColor
`true` | As shown on the image above, color the Spotify Code bar using cover art colors. | +| spotifyCodeExperimentalSeparateItem
`true` | Separates or joins the Spotify Code Bar to the cover art. Also respects `roundMediaCorners` and `spotifyCodeExperimentalUseColor`.

Spotify code bar separation | + +#### General Theming options +| Key | Description | +| :-- | :-- | | roundMediaCorners
`true` | If cover art (and Spotify Code) should have rounded corners. | | roundProgressBar
`true` | If you want a rounded progress bar. | | showVerticalPipe
`true` | Shows or hides the vertical bar (or pipe) in the module header. | @@ -174,16 +185,14 @@ experimentalCSSOverridesForMM2: [ | alwaysUseDefaultDeviceIcon
`false` | The device icon changes depending on the player type. If you don’t like this behaviour you can disable it. | | experimentalCSSOverridesForMM2
`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) | -## Dynamic Theme -> [!CAUTION] -> Using Dynamic Theming notifications is **deprecated**, use [CSS variables and overrides](#theming-3rd-party-modules). - -The module sends the following notifications on status change: -```js -/* Playing */ { provider: "MMM-OnSpotify", providerPrefix: "ONSP", providerScheme: "VIBRANT", set: "lock" } -/* Player idle */ { provider: "MMM-OnSpotify", set: "unlock" } -``` -You can disable this behaviour using `advertisePlayerTheme: false`. +### MMM-HomeKit +> [!NOTE] +> Im still writting **MMM-HomeKit** to control you mirror. I need help as im currently using HomeAssistant to test it, but I need apple products to actually test if everytying works. Help needed! https://github.com/Fabrizz/MMM-MMM-HomeKit +> - Control your screen on/off, brightness +> - Set the mirror accent color +> - Turn on/off on-screen lyrics +> - Send notifications +> **Nativeliy in the Home app** ## MMM-LiveLyrics View more on the [**MMM-LiveLyrics** repository](https://github.com/Fabrizz/MMM-LiveLyrics). This module uses web scrapping to get the Lyrics from Genius. Not recommended for basic usage. @@ -219,6 +228,7 @@ You cannot migrate from NowPlayingInSpotify, as the scopes included in the NPOS textAnimations: true, transitionAnimations: true, spotifyVectorAnimations: true, + scrollAnimations: true, experimentalCSSOverridesForMM2: [ ["--color-text-dimmed", "palette_vibrantlight"], ["--ONSP-OVERRIDES-ICONS-COLOR", "palette_vibrantlight"], @@ -228,11 +238,14 @@ You cannot migrate from NowPlayingInSpotify, as the scopes included in the NPOS ``` # Other: +> [!CAUTION] +> Using Dynamic Theming notifications is **deprecated**, use [CSS variables and overrides](#theming-3rd-party-modules). + - You can disable all the color related theming and use the module as is. You need to disable all the color related fields:
`advertisePlayerTheme`, `useColorInProgressBar`, `useColorInTitle`, `useColorInTitleBorder`, `showBlurBackground`, `useColorInUserData`, `spotifyCodeExperimentalUseColor`, `experimentalCSSOverridesForMM2`. Of course you can still use the Spotify Code (White/Gray). Disabling all theming options also stop the module from loading the [Vibrant](/vendor) lib. - The API for Spotify Codes is not public, as its part of the Spotify CDN (_scannables.scdn.co_). The API could change without notice. Many libraries rely on it and using it does not go againts the ToS. -- Contributions wanted! Add features or your languaje using `translations/yourLanguaje.json`. Currently we have translations for: Spanish, English, German +- Contributions wanted! Add features or your language using `translations/yourLanguage.json`. Currently we have translations for: Spanish, English, German With <3 by Fabrizio | [fabriz.co](https://fabriz.co/) | Star this repository! [Fabrizz logo](https://fabriz.co/) diff --git a/auth/client/assets/clientLogic.js b/auth/client/assets/clientLogic.js index c3d0784..4f2db07 100644 --- a/auth/client/assets/clientLogic.js +++ b/auth/client/assets/clientLogic.js @@ -40,7 +40,7 @@ $.ajax({ url: "https://api.spotify.com/v1/me", headers: { - Authorization: "Bearer " + params.access_token, + Authorization: `Bearer ${params.access_token}`, }, success: function (response) { step3Placeholder.innerHTML = null; @@ -201,6 +201,6 @@ } function getRedirectURI() { - return window.location.protocol + "//" + window.location.host + "/callback"; + return `${window.location.protocol}//${window.location.host}/callback`; } })(); diff --git a/auth/client/index.html b/auth/client/index.html index 29926b0..9acc1b7 100644 --- a/auth/client/index.html +++ b/auth/client/index.html @@ -20,13 +20,13 @@ src="assets/logo-fabrizz-githubgray.svg" height="48">

MMM-OnSpotify

-

A MagicMirror2 that display what you are listening to using the Spotify Connect API

+

A MagicMirror² that display what you are listening to using the Spotify Connect API

Before we start:

-

To work correctly this module requieres read access to the +

To work correctly this module requires read access to the following scopes in your Spotify Account:

    @@ -184,7 +184,7 @@
    MMM-DolarArgentina
    maintainer, based on the Spotify Auth Example. As its no longer maintained, MMM-OnSpotify was born, this version of the authentication Service includes some QOL changes, more functionality, and its easier - to follow along. (V2.1) + to follow along. (V3.0 New Spotify developers dashboard)

    Turn off the service Restart the tool @@ -195,19 +195,20 @@
    MMM-DolarArgentina
    +

    First, we need to create a new Spotify App using the Spotify Developers Portal. After login in, click on the Create app button.

    +

    Next you need to provide a name and description, what you type doesn’t matter, as it’s just an internal app (Maybe you should use something you’ll recognize in the future). You can left the website blank.

    +

    Now add http://localhost:8100/callback as the redirect URI, so later Spotify knows to redirect here with the credentials.

    +

    To finish the app configuration, click on the Web API checkbox, accept the Spotify ToS and click on Create.

    +

    After successfully creating the app you’ll land on the app’s dashboard. Click on Settings, and then click on the User Management tab.

    +

    There, enter the email associated to your Spotify Account, in the "Full Name" section you can put whatever name/abreviation that you want. Click on Add user to actually save your changes.

    +

    Once you added yourself as a user, go back to the Basic Information tab, there you can see your Client ID and your Client Secret (after clicking on “View client secret”). Check that the redirect URI is correct, then copy and paste both credentials onto the Step 2 card below.

    +