From 45d44a81335c6baa95e6c1fdcbd0157cfe5aa774 Mon Sep 17 00:00:00 2001 From: qianc Date: Fri, 27 Dec 2024 22:22:43 +0100 Subject: [PATCH 1/2] Added functionality to decide which Spotify account to use. --- lib/helpers.js | 9 +++++---- lib/sonos.js | 13 +++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index f83a072..9de5493 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -126,9 +126,10 @@ Helpers.GenerateLocalMetadata = function (uri, artUri = '') { * @param {String} uri The playback uri (currently supports spotify, tunein) * @param {String} title Sometimes the title is required. * @param {String} region Spotify region is required for all spotify tracks, see `sonos.SpotifyRegion` + * @param {String} account Spotify account * @return {Object} options {uri: Spotify uri, metadata: metadata} */ -Helpers.GenerateMetadata = function (uri, title = '', region = '3079') { +Helpers.GenerateMetadata = function (uri, title = '', region = '3079', account = '0') { var parts = uri.split(':') if (!((parts.length === 2 && (parts[0] === 'radio' || parts[0] === 'x-sonosapi-stream' || parts[0] === 'x-rincon-cpcontainer')) || (parts.length >= 3 && parts[0] === 'spotify'))) { debug('Returning string because it isn\'t recognized') @@ -159,7 +160,7 @@ Helpers.GenerateMetadata = function (uri, title = '', region = '3079') { } } } else { - meta = meta.replace('##REGION##', 'SA_RINCON' + region + '_X_#Svc' + region + '-0-Token') + meta = meta.replace('##REGION##', 'SA_RINCON' + region + '_X_#Svc' + region + '-' + account + '-Token') } var spotifyUri = uri.replace(/:/g, '%3a') @@ -231,7 +232,7 @@ Helpers.GenerateMetadata = function (uri, title = '', region = '3079') { .replace('##RESOURCETITLE##', title || 'Sound Cloud Likes') .replace('##SPOTIFYTYPE##', 'object.container.albumList') .replace('##PARENTID##', '') - .replace(`SA_RINCON${region}_X_#Svc${region}-0-Token`, 'SA_RINCON40967_X_#Svc40967-0-Token') + .replace(`SA_RINCON${region}_X_#Svc${region}-${account}-Token`, 'SA_RINCON40967_X_#Svc40967-${account}-Token') } } else if (uri.startsWith('x-rincon-cpcontainer:1006206cplaylist')) { // Sound Cloud playlists const [id] = uri.replace('x-rincon-cpcontainer:', '').split('?') @@ -241,7 +242,7 @@ Helpers.GenerateMetadata = function (uri, title = '', region = '3079') { .replace('##RESOURCETITLE##', title || 'Sound Cloud Playlist') .replace('##SPOTIFYTYPE##', 'object.container.playlistContainer') .replace('##PARENTID##', '') - .replace(`SA_RINCON${region}_X_#Svc${region}-0-Token`, 'SA_RINCON40967_X_#Svc40967-0-Token') + .replace(`SA_RINCON${region}_X_#Svc${region}-${account}-Token`, 'SA_RINCON40967_X_#Svc40967-${account}-Token') } } else { return { uri: uri, metadata: '' } diff --git a/lib/sonos.js b/lib/sonos.js index 4ad7f95..aa16e9f 100644 --- a/lib/sonos.js +++ b/lib/sonos.js @@ -61,6 +61,7 @@ var Sonos = function Sonos (host, port, options) { this.options.spotify = this.options.spotify || {} this.options.spotify.region = this.options.spotify.region || SpotifyRegion.US + this.options.spotify.account_token = this.options.spotify.account_token || '0' // Attach to newListener event var self = this @@ -185,7 +186,7 @@ Sonos.prototype.addToPlaylist = async function (playlistId, uri) { debug('Sonos.addToPlaylist(%j, %j)', playlistId, uri) const result = await this.getPlaylist(playlistId) - const meta = Helpers.GenerateMetadata(uri, undefined, this.options.spotify.region) + const meta = Helpers.GenerateMetadata(uri, undefined, this.options.spotify.region, this.options.spotify.account_token) return this.avTransportService().AddURIToSavedQueue({ InstanceID: 0, @@ -318,7 +319,7 @@ Sonos.prototype.setAVTransportURI = async function (options) { } // If the options is a string try to generate metadata from it - if (typeof options === 'string') options = Helpers.GenerateMetadata(options, undefined, this.options.spotify.region) + if (typeof options === 'string') options = Helpers.GenerateMetadata(options, undefined, this.options.spotify.region, this.options.spotify.account_token) // We need this later. const self = this @@ -511,7 +512,7 @@ Sonos.prototype.playTuneinRadio = async function (stationId, stationTitle) { */ Sonos.prototype.playSpotifyRadio = async function (artistId, artistName) { debug('Sonos.playSpotifyRadio(%j, %j)', artistId, artistName) - var options = Helpers.GenerateMetadata('spotify:artistRadio:' + artistId, artistName, this.options.spotify.region) + var options = Helpers.GenerateMetadata('spotify:artistRadio:' + artistId, artistName, this.options.spotify.region, this.options.spotify.account_token) return this.setAVTransportURI(options) } @@ -524,7 +525,7 @@ Sonos.prototype.playSpotifyRadio = async function (artistId, artistName) { */ Sonos.prototype.queue = async function (options, positionInQueue = 0) { debug('Sonos.queue(%j, %j)', options, positionInQueue) - if (typeof options === 'string') options = Helpers.GenerateMetadata(options, undefined, this.options.spotify.region) + if (typeof options === 'string') options = Helpers.GenerateMetadata(options, undefined, this.options.spotify.region, this.options.spotify.account_token) return this.avTransportService().AddURIToQueue({ InstanceID: 0, EnqueuedURI: Helpers.EncodeXml(options.uri), @@ -856,6 +857,10 @@ Sonos.prototype.setSpotifyRegion = function (region) { this.options.spotify.region = region } +Sonos.prototype.setSpotifyAccountToken = function (token) { + this.options.spotify.account_token = token +} + /** * Get the current queue * @returns {Object} {returned: {String}, total: {String}, items:[{title:{String}, uri: {String}}]} From 94a8a150e03a1770925d455b55dd54f6ce981f8b Mon Sep 17 00:00:00 2001 From: qianc Date: Fri, 27 Dec 2024 22:29:59 +0100 Subject: [PATCH 2/2] Updated doc with Spotify account --- docs/helpers.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/helpers.md b/docs/helpers.md index a6d9653..b3bcf8a 100644 --- a/docs/helpers.md +++ b/docs/helpers.md @@ -90,6 +90,8 @@ Creates object with uri and metadata from playback uri **region**: `String`, Spotify region is required for all spotify tracks, see `sonos.SpotifyRegion` +**account**: `String`, Spotify account + **Returns**: `Object`, options {uri: Spotify uri, metadata: metadata} ### sonos.Helpers.ParseDIDL(didl, host, port)