spotifywebapiPython 1.0.153__py3-none-any.whl → 1.0.155__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of spotifywebapiPython might be problematic. Click here for more details.

Files changed (22) hide show
  1. {spotifywebapiPython-1.0.153.dist-info → spotifywebapiPython-1.0.155.dist-info}/METADATA +1 -1
  2. {spotifywebapiPython-1.0.153.dist-info → spotifywebapiPython-1.0.155.dist-info}/RECORD +22 -22
  3. spotifywebapipython/const.py +1 -1
  4. spotifywebapipython/docs/__init__.html +16 -2
  5. spotifywebapipython/docs/index.html +2 -2
  6. spotifywebapipython/docs/search.js +1 -1
  7. spotifywebapipython/docs/spotifywebapipython/const.html +3 -3
  8. spotifywebapipython/docs/spotifywebapipython/saappmessages.html +2 -2
  9. spotifywebapipython/docs/spotifywebapipython/sautils.html +2 -2
  10. spotifywebapipython/docs/spotifywebapipython/spotifyapierror.html +2 -2
  11. spotifywebapipython/docs/spotifywebapipython/spotifyapimessage.html +2 -2
  12. spotifywebapipython/docs/spotifywebapipython/spotifyauthtoken.html +2 -2
  13. spotifywebapipython/docs/spotifywebapipython/spotifyclient.html +6 -3
  14. spotifywebapipython/docs/spotifywebapipython/spotifydiscovery.html +2 -2
  15. spotifywebapipython/docs/spotifywebapipython/spotifywebapiauthenticationerror.html +2 -2
  16. spotifywebapipython/docs/spotifywebapipython/spotifywebapierror.html +2 -2
  17. spotifywebapipython/docs/spotifywebapipython/spotifywebplayertoken.html +2 -2
  18. spotifywebapipython/spotifyclient.py +225 -81
  19. spotifywebapipython/spotifyconnect/spotifyconnectdirectorytask.py +1 -1
  20. {spotifywebapiPython-1.0.153.dist-info → spotifywebapiPython-1.0.155.dist-info}/LICENSE +0 -0
  21. {spotifywebapiPython-1.0.153.dist-info → spotifywebapiPython-1.0.155.dist-info}/WHEEL +0 -0
  22. {spotifywebapiPython-1.0.153.dist-info → spotifywebapiPython-1.0.155.dist-info}/top_level.txt +0 -0
@@ -10,6 +10,7 @@ from soco.core import (
10
10
  PLAY_MODE_BY_MEANING as SONOS_PLAY_MODE_BY_MEANING,
11
11
  PLAY_MODES as SONOS_PLAY_MODES,
12
12
  )
13
+ from soco.plugins.sharelink import ShareLinkPlugin
13
14
  import time
14
15
  from typing import Tuple, Callable, Union
15
16
  from urllib3 import PoolManager, Timeout, HTTPResponse
@@ -1190,6 +1191,9 @@ class SpotifyClient:
1190
1191
  This API only works for users who have Spotify Premium.
1191
1192
 
1192
1193
  The order of execution is not guaranteed when you use this API with other Player API endpoints.
1194
+
1195
+ For Sonos devices, items are added to the end of the device local queue.
1196
+ For non-Sonos devices, items are added to the end of the user's current playback queue.
1193
1197
 
1194
1198
  The Spotify Web API endpoint is called to add each item individually.
1195
1199
  The Spotify Web API does not currently support adding more than 1 item to the queue at a time.
@@ -1229,30 +1233,52 @@ class SpotifyClient:
1229
1233
 
1230
1234
  # resolve / activate the device object if needed.
1231
1235
  scDevice:SpotifyConnectDevice = self._ResolveDeviceObject(deviceId, False)
1232
-
1233
- # process all uri's.
1234
- for idx in range(0, len(arrUris)):
1235
-
1236
- # build spotify web api request parameters.
1237
- urlParms:dict = \
1238
- {
1239
- 'uri': arrUris[idx]
1240
- }
1241
- if (scDevice is not None):
1242
- urlParms['device_id'] = scDevice.Id
1243
1236
 
1244
- # execute spotify web api request.
1245
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/queue')
1246
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
1247
- msg.UrlParameters = urlParms
1248
- self.MakeRequest('POST', msg)
1237
+ # is this a Sonos device?
1238
+ if (scDevice is not None) and (scDevice.IsSonos):
1249
1239
 
1250
- # give spotify web api time to process the change.
1251
- if delay > 0:
1252
- _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
1253
- time.sleep(delay)
1240
+ # trace.
1241
+ _logsi.LogVerbose("Items will be added to Sonos local queue for device: %s" % (scDevice.Title))
1242
+
1243
+ # get the Sonos Controller player instance.
1244
+ sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
1245
+
1246
+ # add all track items to the Sonos local queue.
1247
+ sharelink = ShareLinkPlugin(sonosPlayer)
1248
+ for idx in range(0, len(arrUris)):
1249
+
1250
+ # add track to the Sonos local queue.
1251
+ uri = arrUris[idx].strip()
1252
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": ADD_SHARE_LINK_TO_QUEUE (uri=%s)" % (scDevice.Name, uri))
1253
+ sharelink.add_share_link_to_queue(uri)
1254
+
1255
+ else:
1256
+
1257
+ # trace.
1258
+ _logsi.LogVerbose("Items will be added to playback queue for device: %s" % (scDevice.Title))
1259
+
1260
+ # process all uri's.
1261
+ for idx in range(0, len(arrUris)):
1262
+
1263
+ # build spotify web api request parameters.
1264
+ urlParms:dict = \
1265
+ {
1266
+ 'uri': arrUris[idx]
1267
+ }
1268
+ if (scDevice is not None):
1269
+ urlParms['device_id'] = scDevice.Id
1270
+
1271
+ # execute spotify web api request.
1272
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/queue')
1273
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
1274
+ msg.UrlParameters = urlParms
1275
+ self.MakeRequest('POST', msg)
1276
+
1277
+ # give spotify web api time to process the change.
1278
+ if delay > 0:
1279
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
1280
+ time.sleep(delay)
1254
1281
 
1255
-
1256
1282
  # process results.
1257
1283
  # no results to process - this is pass or fail.
1258
1284
  return
@@ -11697,36 +11723,117 @@ class SpotifyClient:
11697
11723
 
11698
11724
  # validations.
11699
11725
  delay = validateDelay(delay, 0.50, 10)
11726
+ if (positionMS is None) or (positionMS < 0):
11727
+ positionMS = 0
11728
+ if (offsetPosition is None) or (offsetPosition < 0):
11729
+ offsetPosition = 0
11700
11730
 
11701
11731
  # resolve / activate the device object if needed.
11702
11732
  scDevice = self._ResolveDeviceObject(deviceId, False)
11703
11733
 
11704
- # build spotify web api request parameters.
11705
- reqData:dict = \
11706
- {
11707
- 'context_uri': contextUri,
11708
- 'position_ms': positionMS
11709
- }
11710
- if offsetUri is not None:
11711
- reqData['offset'] = { 'uri': offsetUri }
11712
- elif offsetPosition is not None:
11713
- reqData['offset'] = { 'position': offsetPosition }
11734
+ # is this a Sonos device?
11735
+ if (scDevice is not None) and (scDevice.IsSonos):
11714
11736
 
11715
- # formulate url parms; will manually add them since we are adding json body as well.
11716
- urlParms:str = ''
11717
- if (scDevice is not None):
11718
- urlParms = '?device_id=%s' % scDevice.Id
11737
+ # trace.
11738
+ _logsi.LogVerbose("Context will be played on Sonos local queue for device: %s" % (scDevice.Title))
11739
+
11740
+ # Sonos cannot handle playing an artist context!
11741
+ # if this is an artist context, then we will get a list of the artist's albums
11742
+ # and add them to the queue.
11743
+ if (contextUri.find(':artist:') > -1):
11744
+ artistId:str = contextUri.replace('spotify:artist:','')
11745
+ #includeGroups:str = 'album,single,appears_on,compilation'
11746
+ includeGroups:str = 'album'
11747
+ _logsi.LogVerbose("Getting ALL albums for artist id: %s" % (artistId))
11748
+ pageObj:AlbumPageSimplified = self.GetArtistAlbums(artistId, includeGroups, limitTotal=75)
11749
+ contextUri:list = []
11750
+ albumSimplified:AlbumSimplified
11751
+ for albumSimplified in pageObj.Items:
11752
+ contextUri.append(albumSimplified.Uri)
11753
+
11754
+ # build a list of all item uri's.
11755
+ # remove any leading / trailing spaces in case user put a space between the items.
11756
+ arrUris:list[str] = None
11757
+ if isinstance(contextUri, list):
11758
+ arrUris = contextUri
11759
+ else:
11760
+ arrUris = contextUri.split(',')
11761
+ for idx in range(0, len(arrUris)):
11762
+ arrUris[idx] = arrUris[idx].strip()
11719
11763
 
11720
- # execute spotify web api request.
11721
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/play{url_parms}'.format(url_parms=urlParms))
11722
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11723
- msg.RequestJson = reqData
11724
- self.MakeRequest('PUT', msg)
11764
+ # get the Sonos Controller player instance.
11765
+ sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
11766
+
11767
+ # clear the Sonos local queue.
11768
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": CLEAR_QUEUE" % (scDevice.Name))
11769
+ sonosPlayer.clear_queue()
11770
+
11771
+ # add all context items to the Sonos local queue.
11772
+ sharelink = ShareLinkPlugin(sonosPlayer)
11773
+ for idx in range(0, len(arrUris)):
11774
+
11775
+ # add context to the Sonos local queue.
11776
+ uri = arrUris[idx].strip()
11777
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": ADD_SHARE_LINK_TO_QUEUE (uri=%s)" % (scDevice.Name, uri))
11778
+ sharelink.add_share_link_to_queue(uri)
11779
+
11780
+ # if this is the first item added, then start play of the queue as
11781
+ # it may take awhile to load the rest of the items.
11782
+ if (idx == 0):
11783
+
11784
+ # start playing the Sonos local queue.
11785
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": PLAY_FROM_QUEUE (index=%s)" % (scDevice.Name, offsetPosition))
11786
+ sonosPlayer.play_from_queue(index=offsetPosition)
11787
+
11788
+ # # give Sonos Controller time to process the change.
11789
+ # if delay > 0:
11790
+ # _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE_SONOS % delay)
11791
+ # time.sleep(delay)
11792
+
11793
+ # was a track seek position specified?
11794
+ if (positionMS > 0):
11795
+
11796
+ # seek to the position in the track.
11797
+ sonosPosition:str = mediaPositionHMS_fromSeconds(positionMS / 1000) # convert from milliseconds to Sonos H:MM:SS format
11798
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": SEEK (position=%s)" % (scDevice.Name, sonosPosition))
11799
+ sonosPlayer.seek(position=sonosPosition)
11800
+
11801
+ # give Sonos Controller time to process the change.
11802
+ if delay > 0:
11803
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE_SONOS % delay)
11804
+ time.sleep(delay)
11805
+
11806
+ else:
11807
+
11808
+ # trace.
11809
+ _logsi.LogVerbose("Context will be played on the Spotify Connect device via Spotify Web API")
11810
+
11811
+ # build spotify web api request parameters.
11812
+ reqData:dict = \
11813
+ {
11814
+ 'context_uri': contextUri,
11815
+ 'position_ms': positionMS
11816
+ }
11817
+ if offsetUri is not None:
11818
+ reqData['offset'] = { 'uri': offsetUri }
11819
+ else:
11820
+ reqData['offset'] = { 'position': offsetPosition }
11821
+
11822
+ # formulate url parms; will manually add them since we are adding json body as well.
11823
+ urlParms:str = ''
11824
+ if (scDevice is not None):
11825
+ urlParms = '?device_id=%s' % scDevice.Id
11826
+
11827
+ # execute spotify web api request.
11828
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/play{url_parms}'.format(url_parms=urlParms))
11829
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
11830
+ msg.RequestJson = reqData
11831
+ self.MakeRequest('PUT', msg)
11725
11832
 
11726
- # give spotify web api time to process the change.
11727
- if delay > 0:
11728
- _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
11729
- time.sleep(delay)
11833
+ # give spotify web api time to process the change.
11834
+ if delay > 0:
11835
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
11836
+ time.sleep(delay)
11730
11837
 
11731
11838
  # process results.
11732
11839
  # no results to process - this is pass or fail.
@@ -11952,6 +12059,9 @@ class SpotifyClient:
11952
12059
 
11953
12060
  # validations.
11954
12061
  delay = validateDelay(delay, 0.50, 10)
12062
+ if (positionMS is None) or (positionMS < 0):
12063
+ positionMS = 0
12064
+ offsetPosition:int = 0
11955
12065
 
11956
12066
  # build a list of all item uri's.
11957
12067
  # remove any leading / trailing spaces in case user put a space between the items.
@@ -11964,50 +12074,84 @@ class SpotifyClient:
11964
12074
  arrUris[idx] = arrUris[idx].strip()
11965
12075
 
11966
12076
  # resolve / activate the device object if needed.
11967
- scDevice = self._ResolveDeviceObject(deviceId, False)
12077
+ scDevice = self._ResolveDeviceObject(deviceId, True)
11968
12078
 
11969
- # left this here in case we want to implement it in the future.
11970
-
11971
- # # are we backfilling the player queue? if so, we can only have 50 uris total.
11972
- # if (backfillUrisPageOffset > -1) and (len(arrUris) < 50):
12079
+ # is this a Sonos device?
12080
+ if (scDevice is not None) and (scDevice.IsSonos):
11973
12081
 
11974
- # # are we playing tracks?
11975
- # if (len(arrUris) > 0) and (SpotifyClient.GetTypeFromUri(arrUris[0]) == 'track'):
11976
-
11977
- # _logsi.LogVerbose("Backfilling player queue items from users top tracks")
12082
+ # trace.
12083
+ _logsi.LogVerbose("Track list will be played on Sonos local queue for device: %s" % (scDevice.Title))
12084
+
12085
+ # get the Sonos Controller player instance.
12086
+ sonosPlayer:SoCo = self.SpotifyConnectDirectory.GetSonosPlayer(scDevice)
12087
+
12088
+ # clear the Sonos local queue.
12089
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": CLEAR_QUEUE" % (scDevice.Name))
12090
+ sonosPlayer.clear_queue()
12091
+
12092
+ # add all track items to the Sonos local queue.
12093
+ sharelink = ShareLinkPlugin(sonosPlayer)
12094
+ for idx in range(0, len(arrUris)):
12095
+
12096
+ # add track to the Sonos local queue.
12097
+ uri = arrUris[idx].strip()
12098
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": ADD_SHARE_LINK_TO_QUEUE (uri=%s)" % (scDevice.Name, uri))
12099
+ sharelink.add_share_link_to_queue(uri)
12100
+
12101
+ # if this is the first item added, then start play of the queue as
12102
+ # it may take awhile to load the rest of the items.
12103
+ if (idx == 0):
12104
+
12105
+ # start playing the Sonos local queue.
12106
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": PLAY_FROM_QUEUE (index=%s)" % (scDevice.Name, offsetPosition))
12107
+ sonosPlayer.play_from_queue(index=offsetPosition)
11978
12108
 
11979
- # # get list of users top tracks (50 max items).
11980
- # pageObj:TrackPage = self.GetUsersTopTracks(timeRange='medium_term', offset=backfillUrisPageOffset, limit=(50 - len(arrUris)), sortResult=False)
12109
+ # # give Sonos Controller time to process the change.
12110
+ # if delay > 0:
12111
+ # _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE_SONOS % delay)
12112
+ # time.sleep(delay)
12113
+
12114
+ # was a track seek position specified?
12115
+ if (positionMS > 0):
12116
+
12117
+ # seek to the position in the track.
12118
+ sonosPosition:str = mediaPositionHMS_fromSeconds(positionMS / 1000) # convert from milliseconds to Sonos H:MM:SS format
12119
+ _logsi.LogVerbose("Issuing command to Sonos device \"%s\": SEEK (position=%s)" % (scDevice.Name, sonosPosition))
12120
+ sonosPlayer.seek(position=sonosPosition)
11981
12121
 
11982
- # # add them to the player queue; no need to validate the device id, since we
11983
- # # know there is an active device id by this point.
11984
- # item:Track
11985
- # for item in pageObj.Items:
11986
- # arrUris.append(item.Uri)
12122
+ # give Sonos Controller time to process the change.
12123
+ if delay > 0:
12124
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE_SONOS % delay)
12125
+ time.sleep(delay)
11987
12126
 
11988
- # build spotify web api request parameters.
11989
- reqData:dict = \
11990
- {
11991
- 'position_ms': positionMS
11992
- }
11993
- if uris is not None:
11994
- reqData['uris'] = arrUris
12127
+ else:
11995
12128
 
11996
- # formulate url parms; will manually add them since we are adding json body as well.
11997
- urlParms:str = ''
11998
- if (scDevice is not None):
11999
- urlParms = '?device_id=%s' % scDevice.Id
12129
+ # trace.
12130
+ _logsi.LogVerbose("Track list will be played on the Spotify Connect device via Spotify Web API")
12000
12131
 
12001
- # execute spotify web api request.
12002
- msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/play{url_parms}'.format(url_parms=urlParms))
12003
- msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
12004
- msg.RequestJson = reqData
12005
- self.MakeRequest('PUT', msg)
12132
+ # build spotify web api request parameters.
12133
+ reqData:dict = \
12134
+ {
12135
+ 'position_ms': positionMS
12136
+ }
12137
+ if uris is not None:
12138
+ reqData['uris'] = arrUris
12139
+
12140
+ # formulate url parms; will manually add them since we are adding json body as well.
12141
+ urlParms:str = ''
12142
+ if (scDevice is not None):
12143
+ urlParms = '?device_id=%s' % scDevice.Id
12144
+
12145
+ # execute spotify web api request.
12146
+ msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, '/me/player/play{url_parms}'.format(url_parms=urlParms))
12147
+ msg.RequestHeaders[self.AuthToken.HeaderKey] = self.AuthToken.HeaderValue
12148
+ msg.RequestJson = reqData
12149
+ self.MakeRequest('PUT', msg)
12006
12150
 
12007
- # give spotify web api time to process the change.
12008
- if delay > 0:
12009
- _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
12010
- time.sleep(delay)
12151
+ # give spotify web api time to process the change.
12152
+ if delay > 0:
12153
+ _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE % delay)
12154
+ time.sleep(delay)
12011
12155
 
12012
12156
  # process results.
12013
12157
  # no results to process - this is pass or fail.
@@ -13023,7 +13167,7 @@ class SpotifyClient:
13023
13167
  sonosPlayer.play()
13024
13168
  wasCmdIssued = True
13025
13169
 
13026
- # give SoCo api time to process the change.
13170
+ # give Sonos Controller time to process the change.
13027
13171
  if (wasCmdIssued) and (delay > 0):
13028
13172
  _logsi.LogVerbose(TRACE_MSG_DELAY_DEVICE_SONOS % delay)
13029
13173
  time.sleep(delay)
@@ -1308,7 +1308,7 @@ class SpotifyConnectDirectoryTask(threading.Thread):
1308
1308
 
1309
1309
  # if playerState object not supplied, then go get it.
1310
1310
  if (playerState is None):
1311
- playerState:PlayerPlayState = self._SpotifyClientInstance.GetPlayerPlaybackState()
1311
+ playerState:PlayerPlayState = self._SpotifyClientInstance.GetPlayerPlaybackState(additionalTypes='episode')
1312
1312
 
1313
1313
  # if valid object then process it.
1314
1314
  if (isinstance(playerState, PlayerPlayState)):