diff --git a/docs/helpers.md b/docs/helpers.md index a6d9653d..b3bcf8ae 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) diff --git a/lib/helpers.js b/lib/helpers.js index 6b82ab01..55ffaa71 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -126,10 +126,11 @@ 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') { - const parts = uri.split(':') +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') return Helpers.GenerateLocalMetadata(uri) @@ -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') } const 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, metadata: '' } diff --git a/lib/sonos.js b/lib/sonos.js index de8e8416..1b9d8e48 100644 --- a/lib/sonos.js +++ b/lib/sonos.js @@ -61,6 +61,7 @@ const 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 const 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) - const 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}}]}