diff --git a/.gitignore b/.gitignore
index d7d4895..bd1fb64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,4 +43,5 @@ ex.json
test.json
api.json
svgs.html
+lyrics.js
diff --git a/.prettierrc b/.prettierrc
index f2e4215..00d0fb2 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -4,5 +4,6 @@
"trailingComma": "all",
"bracketSpacing": true,
"arrowParens": "always",
- "proseWrap": "always"
+ "proseWrap": "always",
+ "endOfLine": "auto"
}
\ No newline at end of file
diff --git a/MMM-OnSpotify.js b/MMM-OnSpotify.js
index 274cd5b..18a55b5 100644
--- a/MMM-OnSpotify.js
+++ b/MMM-OnSpotify.js
@@ -36,6 +36,8 @@ Module.register("MMM-OnSpotify", {
deviceFilter: [],
deviceFilterExclude: false,
filterNoticeSubtitle: true,
+ // Changes the language sent to Spotify
+ language: config.language,
updateInterval: {
isPlaying: 1,
@@ -143,7 +145,7 @@ Module.register("MMM-OnSpotify", {
typeof this.config.theming.experimentalCSSOverridesForMM2 === "object";
////////////////////////////////////////////////////////////////////////////////////////////
- this.version = "3.3.0";
+ this.version = "3.3.1";
////////////////////////////////////////////////////////////////////////////////////////////
this.displayUser =
@@ -205,6 +207,7 @@ Module.register("MMM-OnSpotify", {
accessToken: this.config.accessToken,
refreshToken: this.config.refreshToken,
},
+ language: this.config.language,
});
this.updateFetchingLoop(this.config.updateInterval[this.lastStatus]);
},
@@ -364,8 +367,9 @@ Module.register("MMM-OnSpotify", {
this.userData = {
...payload,
subtitleOverride:
- this.playerData && this.config.filteredDeviceNotice ?
- this.playerData.notAllowedDevice : false,
+ this.playerData && this.config.filteredDeviceNotice
+ ? this.playerData.notAllowedDevice
+ : false,
};
this.userData.age = Date.now();
this.requestUserData = false;
@@ -664,8 +668,7 @@ Module.register("MMM-OnSpotify", {
? (this.config.theming.textAnimations = this.config.textAnimations)
: null;
typeof this.config.scrollAnimations === "boolean"
- ? (this.config.theming.scrollAnimations =
- this.config.scrollAnimations)
+ ? (this.config.theming.scrollAnimations = this.config.scrollAnimations)
: null;
typeof this.config.spotifyVectorAnimations === "boolean"
? (this.config.theming.spotifyVectorAnimations =
diff --git a/README.md b/README.md
index 8e306ef..7976126 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,7 @@ Once you finish, you are all set with the basic configuration. Scroll down to se
deviceFilter: [],
deviceFilterExclude: false,
filterNoticeSubtitle: true,
+ language: config.language,
// Update intervals [SEE BELOW]
isPlaying: 1,
isEmpty: 2,
@@ -129,6 +130,7 @@ experimentalCSSOverridesForMM2: [
| deviceFilter
`list[]` | List of device names to filter from the module, by default, its an inclusion list, you can change this using `deviceFilterExclude` (making it an exclusion list). When a filtered device plays `displayWhenEmpty` shows. Example: `["Sonos Bedroom", "DESKTOP-ABCD123"]` |
| deviceFilterExclude
`false` | Inverts the `deviceFilter` list, making it exclude devices |
| filterNoticeSubtitle
`true`| Changes the subtitle of `displayWhenEmpty`, to not show a false status if the `deviceFilter` is set |
+| language
`config.language`| Changes the language in which titles of songs are shown. When it is not set, it depends on `config.language`. Example: `en-US` (Or `false` if you prefer the default api response) |
### Polling Intervals:
| Key | Description |
diff --git a/auth/authorization.js b/auth/authorization.js
index a2e1668..3cfa7ac 100644
--- a/auth/authorization.js
+++ b/auth/authorization.js
@@ -11,10 +11,9 @@
* and Raywoo implementation:
* https://github.com/raywo/MMM-NowPlayingOnSpotify/tree/master/authorization
*/
-
+const querystring = require("querystring");
const express = require("express");
const request = require("request");
-const querystring = require("querystring");
const cookieParser = require("cookie-parser");
const bodyParser = require("body-parser");
@@ -75,9 +74,9 @@ function getAuthOptions(code) {
grant_type: "authorization_code",
},
headers: {
- Authorization:
- "Basic " +
- Buffer.from(client_id + ":" + client_secret).toString("base64"),
+ Authorization: `Basic ${Buffer.from(
+ `${client_id}:${client_secret}`,
+ ).toString("base64")}`,
},
json: true,
};
@@ -88,19 +87,18 @@ function redirectToSuccess(response, body) {
let refresh_token = body.refresh_token;
// we can also pass the token to the browser to make requests from there
response.redirect(
- "/#" +
- querystring.stringify({
- access_token: access_token,
- refresh_token: refresh_token,
- client_id: client_id,
- client_secret: client_secret,
- }),
+ `/#${querystring.stringify({
+ access_token: access_token,
+ refresh_token: refresh_token,
+ client_id: client_id,
+ client_secret: client_secret,
+ })}`,
);
}
let stateKey = "spotify_auth_state";
let app = express();
-app.use(express.static(__dirname + "/client"));
+app.use(express.static(`${__dirname}/client`));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
diff --git a/node_helper.js b/node_helper.js
index dd64050..e2f9f0f 100644
--- a/node_helper.js
+++ b/node_helper.js
@@ -30,7 +30,7 @@ module.exports = NodeHelper.create({
case "SET_CREDENTIALS_REFRESH":
this.fetcher = new SpotifyFetcher(payload);
this.fetchSpotifyData("PLAYER");
- this.preferences = payload.preferences
+ this.preferences = payload.preferences;
break;
case "REFRESH_PLAYER":
this.fetchSpotifyData("PLAYER");
@@ -61,7 +61,12 @@ module.exports = NodeHelper.create({
switch (type) {
case "PLAYER":
// CASE S1 The data is OK and the target is a filtered device
- if (data && data.device && data.device.name && !this.isAllowedDevice(data.device.name)) {
+ if (
+ data &&
+ data.device &&
+ data.device.name &&
+ !this.isAllowedDevice(data.device.name)
+ ) {
this.sendSocketNotification("PLAYER_DATA", {
statusIsPlayerEmpty: true,
statusIsNewSong: false,
@@ -69,15 +74,15 @@ module.exports = NodeHelper.create({
statusIsChangeToMediaPlayer: false,
statusPlayerUpdating: false,
statusIsDeviceChange: false,
- notAllowedDevice: data.device.name
+ notAllowedDevice: data.device.name,
});
this.lastMediaUri = "empty";
this.lastPlayerStatus = false;
this.lastPlayerStatusCount = 0;
this.lastDeviceName = "unknown";
- break
+ break;
}
- // CASE S2 The data is OK and the target is in a private session
+ // CASE S2 The data is OK and the target is in a private session
if (data && data.device && data.device.is_private_session) {
let payload = {
/* Player data */
@@ -97,7 +102,7 @@ module.exports = NodeHelper.create({
statusPlayerUpdating: false,
statusIsDeviceChange:
this.lastDeviceName !== data.device.name ? true : false,
- notAllowedDevice: false
+ notAllowedDevice: false,
};
this.sendSocketNotification("PLAYER_DATA", payload);
this.lastMediaUri = "privatesession";
@@ -150,7 +155,7 @@ module.exports = NodeHelper.create({
statusPlayerUpdating: false,
statusIsDeviceChange:
this.lastDeviceName !== data.device.name ? true : false,
- notAllowedDevice: false
+ notAllowedDevice: false,
};
this.sendSocketNotification("PLAYER_DATA", payload);
this.lastMediaUri = data.item.uri;
@@ -169,7 +174,7 @@ module.exports = NodeHelper.create({
statusIsChangeToMediaPlayer: false,
statusPlayerUpdating: true,
statusIsDeviceChange: false,
- notAllowedDevice: false
+ notAllowedDevice: false,
});
this.lastPlayerStatusCount = this.lastPlayerStatusCount + 1;
this.lastPlayerStatus = true;
@@ -182,7 +187,7 @@ module.exports = NodeHelper.create({
statusIsChangeToMediaPlayer: false,
statusPlayerUpdating: false,
statusIsDeviceChange: false,
- notAllowedDevice: false
+ notAllowedDevice: false,
});
this.lastMediaUri = "empty";
this.lastPlayerStatus = false;
@@ -197,7 +202,7 @@ module.exports = NodeHelper.create({
statusIsChangeToMediaPlayer: false,
statusPlayerUpdating: false,
statusIsDeviceChange: false,
- notAllowedDevice: false
+ notAllowedDevice: false,
});
this.lastMediaUri = "empty";
this.lastPlayerStatus = false;
@@ -254,10 +259,14 @@ module.exports = NodeHelper.create({
},
isAllowedDevice: function (currentDevice) {
- if (!this.preferences.deviceFilter || this.preferences.deviceFilter.length < 1) return true
- return this.preferences.deviceFilterExclude ?
- !this.preferences.deviceFilter.includes(currentDevice) :
- this.preferences.deviceFilter.includes(currentDevice)
+ if (
+ !this.preferences.deviceFilter ||
+ this.preferences.deviceFilter.length < 1
+ )
+ return true;
+ return this.preferences.deviceFilterExclude
+ ? !this.preferences.deviceFilter.includes(currentDevice)
+ : this.preferences.deviceFilter.includes(currentDevice);
},
processArtists: (artists) => artists.map((artist) => artist.name).join(", "),
processImages: (images) => {
diff --git a/package.json b/package.json
index ac436e9..2f9b865 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "mmm-onspotify",
- "version": "3.3.0",
+ "version": "3.3.1",
"description": "A MagicMirror2 module to display Spotify Connect data. Highly customizable. Allows DynamicTheming.",
"repository": {
"type": "git",
diff --git a/translations/en.json b/translations/en.json
index 3ff6669..df48104 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -3,17 +3,17 @@
"FILTERED_PLAYING": "Nothing is playing in this room.",
"PRODUCT_WARNING": "The current account is not using Spotify Premium. This module requieres a Premium account.",
"CONNECTION_WARNING": "There was a connection error. Slowing the polling of api.spotify/...",
- "CONNECTION_ERROR": "Connection errors persists. Slowing the polling more. Hiding old player data.",
- "VIBRANT_NOT_LOADED": "(vendor) Vibrant did not load correctly.",
- "USER_CSS_ERROR": "There was an error extracting CSS information. (The duration of animations/transitions should be in \"ms\")",
+ "CONNECTION_ERROR": "Connection errors persist. Slowing the polling rate to seconds. Emptying player as the data is outdated.",
+ "VIBRANT_NOT_LOADED": "[VENDOR] Vibrant library did not load correctly.",
+ "USER_CSS_ERROR": "An error ocurred while extracting CSS information. (The duration of animations/transitions should be in \"ms\")",
"STABLISHING_CONNECTION": "Connecting to Spotify...",
"NOTHING_PLAYING": "Nothing is playing",
"SPOTIFY_HEADER": "MMM-OnSpotify",
- "DEBUG_COLORS": "Debug palettes are shown because is set to true",
- "SPOTIFYCODE_EXPERIMENTAL": " is enabled. The api to generate codes is not public, and can end without prior notice. (https://github.com/Fabrizz/MMM-OnSpotify#other)",
+ "DEBUG_COLORS": " is enabled. The module will log Vibrant data when color processing is requested.",
+ "SPOTIFYCODE_EXPERIMENTAL": " is enabled. The API used is not documented, as its an Spotify service. This service could stop working at any time. (https://github.com/Fabrizz/MMM-OnSpotify#other)",
"RESUME": "Resuming module",
"SUSPEND": "Suspending module",
- "LIVELYRICS_NOTICE": "MMM-LiveLyrics found! - Check MMM-LL logs to see more. (https://github.com/Fabrizz/MMM-LiveLyrics)",
- "CSSOVERRIDE_NOTICE": "You are overriding default MM2 CSS variables. Check for spelling errors and contrast issues",
- "CSSOVERRIDE_MALFORMED": "There was an error parsing your \"experimentalCSSOverridesForMM2\" array. Remove your custom config entry or check it for errors"
+ "LIVELYRICS_NOTICE": "MMM-LiveLyrics found! - LiveLyrics should log the connection to this module. (https://github.com/Fabrizz/MMM-LiveLyrics)",
+ "CSSOVERRIDE_NOTICE": "You are overriding default MM2 CSS variables. Check spelling errors (and contrast issues)",
+ "CSSOVERRIDE_MALFORMED": "There was an error parsing your \"experimentalCSSOverridesForMM2\" array. This entry should be an array, check the docs for more information."
}
\ No newline at end of file
diff --git a/utils/SpotifyDomBuilder.js b/utils/SpotifyDomBuilder.js
index 752f92d..f41ee35 100644
--- a/utils/SpotifyDomBuilder.js
+++ b/utils/SpotifyDomBuilder.js
@@ -1191,19 +1191,15 @@ class SpotifyDomBuilder {
document
.getElementById("VSNO-TARGET-SUBTITLE")
.classList.remove("scroll");
- document.getElementById("VSNO-TARGET-TITLE").classList.remove("scroll");
+ document
+ .getElementById("VSNO-TARGET-TITLE")
+ .classList.remove("scroll");
}
}
} catch (error) {
- console.info(
- `%c· MMM-OnSpotify %c %c[INFO]%c Unknown unsync, could not change scroller status`,
- "background-color:#84CC16;color:black;border-radius:0.4em",
- "",
- "background-color:orange;color:black",
- "",
- );
+ /* This effect is based on the current TS of the song, the module reference is going to always be some ms behind,
+ here we catch, any even if it never happens, the error thown if the player changes state */
}
-
}
/* Utils */
diff --git a/utils/SpotifyFetcher.js b/utils/SpotifyFetcher.js
index dd8e26a..8a68ceb 100644
--- a/utils/SpotifyFetcher.js
+++ b/utils/SpotifyFetcher.js
@@ -16,6 +16,7 @@ module.exports = class SpotifyFetcher {
constructor(payload) {
this.credentials = payload.credentials;
this.preferences = payload.preferences;
+ this.language = payload.language;
this.tokenExpiresAt = moment();
}
@@ -40,6 +41,10 @@ module.exports = class SpotifyFetcher {
requestData(type) {
let sl = "v1/me/top/artists?limit=9";
+ const headers = new Headers();
+ headers.append("Authorization", `Bearer ${this.credentials.accessToken}`);
+ // TODO: Check if using &locale= (or &market=) has any different effect, as its not documented correctly
+ if (this.language) headers.append("Accept-Language", this.language);
switch (type) {
case "PLAYER":
return fetch(
@@ -47,9 +52,7 @@ module.exports = class SpotifyFetcher {
{
method: "GET",
referrerPolicy: "no-referrer",
- headers: {
- Authorization: `Bearer ${this.credentials.accessToken}`,
- },
+ headers: headers,
},
)
.then((res) => {
@@ -75,7 +78,7 @@ module.exports = class SpotifyFetcher {
return fetch(new URL("v1/me", userBase), {
method: "GET",
referrerPolicy: "no-referrer",
- headers: { Authorization: `Bearer ${this.credentials.accessToken}` },
+ headers: headers,
})
.then((res) => {
if (!res.ok && res.status === 429)
@@ -98,7 +101,7 @@ module.exports = class SpotifyFetcher {
return fetch(new URL("v1/me/player/queue", userBase), {
method: "GET",
referrerPolicy: "no-referrer",
- headers: { Authorization: `Bearer ${this.credentials.accessToken}` },
+ headers: headers,
})
.then((res) => {
if (!res.ok && res.status === 429)
@@ -123,9 +126,7 @@ module.exports = class SpotifyFetcher {
return fetch(new URL(sl, userBase), {
method: "GET",
referrerPolicy: "no-referrer",
- headers: {
- Authorization: `Bearer ${this.credentials.accessToken}`,
- },
+ headers: headers,
})
.then((res) => {
if (!res.ok && res.status === 429)
@@ -148,9 +149,7 @@ module.exports = class SpotifyFetcher {
return fetch(new URL("v1/me/player/recently-played", userBase), {
method: "GET",
referrerPolicy: "no-referrer",
- headers: {
- Authorization: `Bearer ${this.credentials.accessToken}`,
- },
+ headers: headers,
})
.then((res) => {
if (!res.ok && res.status === 429)