Skip to content

Commit b547ef3

Browse files
authored
Merge pull request #47 from Fabrizz/dev-features
Added localization to API response
2 parents 87a8243 + 059fc54 commit b547ef3

10 files changed

Lines changed: 71 additions & 62 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,5 @@ ex.json
4343
test.json
4444
api.json
4545
svgs.html
46+
lyrics.js
4647

.prettierrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"trailingComma": "all",
55
"bracketSpacing": true,
66
"arrowParens": "always",
7-
"proseWrap": "always"
7+
"proseWrap": "always",
8+
"endOfLine": "auto"
89
}

MMM-OnSpotify.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Module.register("MMM-OnSpotify", {
3636
deviceFilter: [],
3737
deviceFilterExclude: false,
3838
filterNoticeSubtitle: true,
39+
// Changes the language sent to Spotify
40+
language: config.language,
3941

4042
updateInterval: {
4143
isPlaying: 1,
@@ -143,7 +145,7 @@ Module.register("MMM-OnSpotify", {
143145
typeof this.config.theming.experimentalCSSOverridesForMM2 === "object";
144146

145147
////////////////////////////////////////////////////////////////////////////////////////////
146-
this.version = "3.3.0";
148+
this.version = "3.3.1";
147149
////////////////////////////////////////////////////////////////////////////////////////////
148150

149151
this.displayUser =
@@ -205,6 +207,7 @@ Module.register("MMM-OnSpotify", {
205207
accessToken: this.config.accessToken,
206208
refreshToken: this.config.refreshToken,
207209
},
210+
language: this.config.language,
208211
});
209212
this.updateFetchingLoop(this.config.updateInterval[this.lastStatus]);
210213
},
@@ -364,8 +367,9 @@ Module.register("MMM-OnSpotify", {
364367
this.userData = {
365368
...payload,
366369
subtitleOverride:
367-
this.playerData && this.config.filteredDeviceNotice ?
368-
this.playerData.notAllowedDevice : false,
370+
this.playerData && this.config.filteredDeviceNotice
371+
? this.playerData.notAllowedDevice
372+
: false,
369373
};
370374
this.userData.age = Date.now();
371375
this.requestUserData = false;
@@ -664,8 +668,7 @@ Module.register("MMM-OnSpotify", {
664668
? (this.config.theming.textAnimations = this.config.textAnimations)
665669
: null;
666670
typeof this.config.scrollAnimations === "boolean"
667-
? (this.config.theming.scrollAnimations =
668-
this.config.scrollAnimations)
671+
? (this.config.theming.scrollAnimations = this.config.scrollAnimations)
669672
: null;
670673
typeof this.config.spotifyVectorAnimations === "boolean"
671674
? (this.config.theming.spotifyVectorAnimations =

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ Once you finish, you are all set with the basic configuration. Scroll down to se
6666
deviceFilter: [],
6767
deviceFilterExclude: false,
6868
filterNoticeSubtitle: true,
69+
language: config.language,
6970
// Update intervals [SEE BELOW]
7071
isPlaying: 1,
7172
isEmpty: 2,
@@ -129,6 +130,7 @@ experimentalCSSOverridesForMM2: [
129130
| deviceFilter <br> `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"]` |
130131
| deviceFilterExclude <br> `false` | Inverts the `deviceFilter` list, making it exclude devices |
131132
| filterNoticeSubtitle <br> `true`| Changes the subtitle of `displayWhenEmpty`, to not show a false status if the `deviceFilter` is set |
133+
| language <br> `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) |
132134

133135
### Polling Intervals:
134136
| Key | Description |

auth/authorization.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@
1111
* and Raywoo implementation:
1212
* https://github.com/raywo/MMM-NowPlayingOnSpotify/tree/master/authorization
1313
*/
14-
14+
const querystring = require("querystring");
1515
const express = require("express");
1616
const request = require("request");
17-
const querystring = require("querystring");
1817
const cookieParser = require("cookie-parser");
1918
const bodyParser = require("body-parser");
2019

@@ -75,9 +74,9 @@ function getAuthOptions(code) {
7574
grant_type: "authorization_code",
7675
},
7776
headers: {
78-
Authorization:
79-
"Basic " +
80-
Buffer.from(client_id + ":" + client_secret).toString("base64"),
77+
Authorization: `Basic ${Buffer.from(
78+
`${client_id}:${client_secret}`,
79+
).toString("base64")}`,
8180
},
8281
json: true,
8382
};
@@ -88,19 +87,18 @@ function redirectToSuccess(response, body) {
8887
let refresh_token = body.refresh_token;
8988
// we can also pass the token to the browser to make requests from there
9089
response.redirect(
91-
"/#" +
92-
querystring.stringify({
93-
access_token: access_token,
94-
refresh_token: refresh_token,
95-
client_id: client_id,
96-
client_secret: client_secret,
97-
}),
90+
`/#${querystring.stringify({
91+
access_token: access_token,
92+
refresh_token: refresh_token,
93+
client_id: client_id,
94+
client_secret: client_secret,
95+
})}`,
9896
);
9997
}
10098

10199
let stateKey = "spotify_auth_state";
102100
let app = express();
103-
app.use(express.static(__dirname + "/client"));
101+
app.use(express.static(`${__dirname}/client`));
104102
app.use(cookieParser());
105103
app.use(bodyParser.json());
106104
app.use(bodyParser.urlencoded({ extended: true }));

node_helper.js

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ module.exports = NodeHelper.create({
3030
case "SET_CREDENTIALS_REFRESH":
3131
this.fetcher = new SpotifyFetcher(payload);
3232
this.fetchSpotifyData("PLAYER");
33-
this.preferences = payload.preferences
33+
this.preferences = payload.preferences;
3434
break;
3535
case "REFRESH_PLAYER":
3636
this.fetchSpotifyData("PLAYER");
@@ -61,23 +61,28 @@ module.exports = NodeHelper.create({
6161
switch (type) {
6262
case "PLAYER":
6363
// CASE S1 The data is OK and the target is a filtered device
64-
if (data && data.device && data.device.name && !this.isAllowedDevice(data.device.name)) {
64+
if (
65+
data &&
66+
data.device &&
67+
data.device.name &&
68+
!this.isAllowedDevice(data.device.name)
69+
) {
6570
this.sendSocketNotification("PLAYER_DATA", {
6671
statusIsPlayerEmpty: true,
6772
statusIsNewSong: false,
6873
statusIsChangeToEmptyPlayer: this.lastPlayerStatus,
6974
statusIsChangeToMediaPlayer: false,
7075
statusPlayerUpdating: false,
7176
statusIsDeviceChange: false,
72-
notAllowedDevice: data.device.name
77+
notAllowedDevice: data.device.name,
7378
});
7479
this.lastMediaUri = "empty";
7580
this.lastPlayerStatus = false;
7681
this.lastPlayerStatusCount = 0;
7782
this.lastDeviceName = "unknown";
78-
break
83+
break;
7984
}
80-
// CASE S2 The data is OK and the target is in a private session
85+
// CASE S2 The data is OK and the target is in a private session
8186
if (data && data.device && data.device.is_private_session) {
8287
let payload = {
8388
/* Player data */
@@ -97,7 +102,7 @@ module.exports = NodeHelper.create({
97102
statusPlayerUpdating: false,
98103
statusIsDeviceChange:
99104
this.lastDeviceName !== data.device.name ? true : false,
100-
notAllowedDevice: false
105+
notAllowedDevice: false,
101106
};
102107
this.sendSocketNotification("PLAYER_DATA", payload);
103108
this.lastMediaUri = "privatesession";
@@ -150,7 +155,7 @@ module.exports = NodeHelper.create({
150155
statusPlayerUpdating: false,
151156
statusIsDeviceChange:
152157
this.lastDeviceName !== data.device.name ? true : false,
153-
notAllowedDevice: false
158+
notAllowedDevice: false,
154159
};
155160
this.sendSocketNotification("PLAYER_DATA", payload);
156161
this.lastMediaUri = data.item.uri;
@@ -169,7 +174,7 @@ module.exports = NodeHelper.create({
169174
statusIsChangeToMediaPlayer: false,
170175
statusPlayerUpdating: true,
171176
statusIsDeviceChange: false,
172-
notAllowedDevice: false
177+
notAllowedDevice: false,
173178
});
174179
this.lastPlayerStatusCount = this.lastPlayerStatusCount + 1;
175180
this.lastPlayerStatus = true;
@@ -182,7 +187,7 @@ module.exports = NodeHelper.create({
182187
statusIsChangeToMediaPlayer: false,
183188
statusPlayerUpdating: false,
184189
statusIsDeviceChange: false,
185-
notAllowedDevice: false
190+
notAllowedDevice: false,
186191
});
187192
this.lastMediaUri = "empty";
188193
this.lastPlayerStatus = false;
@@ -197,7 +202,7 @@ module.exports = NodeHelper.create({
197202
statusIsChangeToMediaPlayer: false,
198203
statusPlayerUpdating: false,
199204
statusIsDeviceChange: false,
200-
notAllowedDevice: false
205+
notAllowedDevice: false,
201206
});
202207
this.lastMediaUri = "empty";
203208
this.lastPlayerStatus = false;
@@ -254,10 +259,14 @@ module.exports = NodeHelper.create({
254259
},
255260

256261
isAllowedDevice: function (currentDevice) {
257-
if (!this.preferences.deviceFilter || this.preferences.deviceFilter.length < 1) return true
258-
return this.preferences.deviceFilterExclude ?
259-
!this.preferences.deviceFilter.includes(currentDevice) :
260-
this.preferences.deviceFilter.includes(currentDevice)
262+
if (
263+
!this.preferences.deviceFilter ||
264+
this.preferences.deviceFilter.length < 1
265+
)
266+
return true;
267+
return this.preferences.deviceFilterExclude
268+
? !this.preferences.deviceFilter.includes(currentDevice)
269+
: this.preferences.deviceFilter.includes(currentDevice);
261270
},
262271
processArtists: (artists) => artists.map((artist) => artist.name).join(", "),
263272
processImages: (images) => {

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mmm-onspotify",
3-
"version": "3.3.0",
3+
"version": "3.3.1",
44
"description": "A MagicMirror2 module to display Spotify Connect data. Highly customizable. Allows DynamicTheming.",
55
"repository": {
66
"type": "git",

translations/en.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33
"FILTERED_PLAYING": "Nothing is playing in this room.",
44
"PRODUCT_WARNING": "The current account is not using Spotify Premium. This module requieres a Premium account.",
55
"CONNECTION_WARNING": "There was a connection error. Slowing the polling of api.spotify/...",
6-
"CONNECTION_ERROR": "Connection errors persists. Slowing the polling more. Hiding old player data.",
7-
"VIBRANT_NOT_LOADED": "(vendor) Vibrant did not load correctly.",
8-
"USER_CSS_ERROR": "There was an error extracting CSS information. (The duration of animations/transitions should be in \"ms\")",
6+
"CONNECTION_ERROR": "Connection errors persist. Slowing the polling rate to <onError> seconds. Emptying player as the data is outdated.",
7+
"VIBRANT_NOT_LOADED": "[VENDOR] Vibrant library did not load correctly.",
8+
"USER_CSS_ERROR": "An error ocurred while extracting CSS information. (The duration of animations/transitions should be in \"ms\")",
99
"STABLISHING_CONNECTION": "Connecting to Spotify...",
1010
"NOTHING_PLAYING": "Nothing is playing",
1111
"SPOTIFY_HEADER": "MMM-OnSpotify",
12-
"DEBUG_COLORS": "Debug palettes are shown because <showDebugPalette> is set to true",
13-
"SPOTIFYCODE_EXPERIMENTAL": "<spotifyCodeExperimentalShow> is enabled. The api to generate codes is not public, and can end without prior notice. (https://github.com/Fabrizz/MMM-OnSpotify#other)",
12+
"DEBUG_COLORS": "<showDebugPalette> is enabled. The module will log Vibrant data when color processing is requested.",
13+
"SPOTIFYCODE_EXPERIMENTAL": "<spotifyCodeExperimentalShow> 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)",
1414
"RESUME": "Resuming module",
1515
"SUSPEND": "Suspending module",
16-
"LIVELYRICS_NOTICE": "MMM-LiveLyrics found! - Check MMM-LL logs to see more. (https://github.com/Fabrizz/MMM-LiveLyrics)",
17-
"CSSOVERRIDE_NOTICE": "You are overriding default MM2 CSS variables. Check for spelling errors and contrast issues",
18-
"CSSOVERRIDE_MALFORMED": "There was an error parsing your \"experimentalCSSOverridesForMM2\" array. Remove your custom config entry or check it for errors"
16+
"LIVELYRICS_NOTICE": "MMM-LiveLyrics found! - LiveLyrics should log the connection to this module. (https://github.com/Fabrizz/MMM-LiveLyrics)",
17+
"CSSOVERRIDE_NOTICE": "You are overriding default MM2 CSS variables. Check spelling errors (and contrast issues)",
18+
"CSSOVERRIDE_MALFORMED": "There was an error parsing your \"experimentalCSSOverridesForMM2\" array. This entry should be an array, check the docs for more information."
1919
}

utils/SpotifyDomBuilder.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,19 +1191,15 @@ class SpotifyDomBuilder {
11911191
document
11921192
.getElementById("VSNO-TARGET-SUBTITLE")
11931193
.classList.remove("scroll");
1194-
document.getElementById("VSNO-TARGET-TITLE").classList.remove("scroll");
1194+
document
1195+
.getElementById("VSNO-TARGET-TITLE")
1196+
.classList.remove("scroll");
11951197
}
11961198
}
11971199
} catch (error) {
1198-
console.info(
1199-
`%c· MMM-OnSpotify %c %c[INFO]%c Unknown unsync, could not change scroller status`,
1200-
"background-color:#84CC16;color:black;border-radius:0.4em",
1201-
"",
1202-
"background-color:orange;color:black",
1203-
"",
1204-
);
1200+
/* This effect is based on the current TS of the song, the module reference is going to always be some ms behind,
1201+
here we catch, any even if it never happens, the error thown if the player changes state */
12051202
}
1206-
12071203
}
12081204

12091205
/* Utils */

utils/SpotifyFetcher.js

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ module.exports = class SpotifyFetcher {
1616
constructor(payload) {
1717
this.credentials = payload.credentials;
1818
this.preferences = payload.preferences;
19+
this.language = payload.language;
1920
this.tokenExpiresAt = moment();
2021
}
2122

@@ -40,16 +41,18 @@ module.exports = class SpotifyFetcher {
4041

4142
requestData(type) {
4243
let sl = "v1/me/top/artists?limit=9";
44+
const headers = new Headers();
45+
headers.append("Authorization", `Bearer ${this.credentials.accessToken}`);
46+
// TODO: Check if using &locale= (or &market=) has any different effect, as its not documented correctly
47+
if (this.language) headers.append("Accept-Language", this.language);
4348
switch (type) {
4449
case "PLAYER":
4550
return fetch(
4651
new URL("v1/me/player?additional_types=track,episode", userBase),
4752
{
4853
method: "GET",
4954
referrerPolicy: "no-referrer",
50-
headers: {
51-
Authorization: `Bearer ${this.credentials.accessToken}`,
52-
},
55+
headers: headers,
5356
},
5457
)
5558
.then((res) => {
@@ -75,7 +78,7 @@ module.exports = class SpotifyFetcher {
7578
return fetch(new URL("v1/me", userBase), {
7679
method: "GET",
7780
referrerPolicy: "no-referrer",
78-
headers: { Authorization: `Bearer ${this.credentials.accessToken}` },
81+
headers: headers,
7982
})
8083
.then((res) => {
8184
if (!res.ok && res.status === 429)
@@ -98,7 +101,7 @@ module.exports = class SpotifyFetcher {
98101
return fetch(new URL("v1/me/player/queue", userBase), {
99102
method: "GET",
100103
referrerPolicy: "no-referrer",
101-
headers: { Authorization: `Bearer ${this.credentials.accessToken}` },
104+
headers: headers,
102105
})
103106
.then((res) => {
104107
if (!res.ok && res.status === 429)
@@ -123,9 +126,7 @@ module.exports = class SpotifyFetcher {
123126
return fetch(new URL(sl, userBase), {
124127
method: "GET",
125128
referrerPolicy: "no-referrer",
126-
headers: {
127-
Authorization: `Bearer ${this.credentials.accessToken}`,
128-
},
129+
headers: headers,
129130
})
130131
.then((res) => {
131132
if (!res.ok && res.status === 429)
@@ -148,9 +149,7 @@ module.exports = class SpotifyFetcher {
148149
return fetch(new URL("v1/me/player/recently-played", userBase), {
149150
method: "GET",
150151
referrerPolicy: "no-referrer",
151-
headers: {
152-
Authorization: `Bearer ${this.credentials.accessToken}`,
153-
},
152+
headers: headers,
154153
})
155154
.then((res) => {
156155
if (!res.ok && res.status === 429)

0 commit comments

Comments
 (0)