improving logging, added null description catching
This commit is contained in:
parent
ccd0754633
commit
6b1ac3ac77
@ -182,6 +182,10 @@ class PlaylistEngine:
|
|||||||
if suffix:
|
if suffix:
|
||||||
string += f' - {str(suffix)}'
|
string += f' - {str(suffix)}'
|
||||||
|
|
||||||
|
if string is None or len(string) == 0:
|
||||||
|
logger.error('no string generated')
|
||||||
|
return None
|
||||||
|
|
||||||
resp = self.net.change_playlist_details(uri, description=string)
|
resp = self.net.change_playlist_details(uri, description=string)
|
||||||
if resp:
|
if resp:
|
||||||
return resp
|
return resp
|
||||||
|
@ -70,7 +70,7 @@ class Network:
|
|||||||
req = requests.get(const.api_url + url, params=params, headers=headers)
|
req = requests.get(const.api_url + url, params=params, headers=headers)
|
||||||
|
|
||||||
if 200 <= req.status_code < 300:
|
if 200 <= req.status_code < 300:
|
||||||
logger.debug(f'{method} get {req.status_code}')
|
logger.debug(f'{method} get {url if whole_url is not None else whole_url} {req.status_code}')
|
||||||
|
|
||||||
if req.status_code != 204:
|
if req.status_code != 204:
|
||||||
return req.json()
|
return req.json()
|
||||||
@ -91,7 +91,7 @@ class Network:
|
|||||||
logger.error(f'{method} rate limit reached: cannot find Retry-After header')
|
logger.error(f'{method} rate limit reached: cannot find Retry-After header')
|
||||||
else:
|
else:
|
||||||
self.refresh_counter = 0
|
self.refresh_counter = 0
|
||||||
logger.critical(f'refresh token limit (5) reached')
|
logger.critical(f'{method} refresh token limit (5) reached')
|
||||||
|
|
||||||
elif req.status_code == 401:
|
elif req.status_code == 401:
|
||||||
logger.warning(f'{method} access token expired, refreshing')
|
logger.warning(f'{method} access token expired, refreshing')
|
||||||
@ -101,7 +101,7 @@ class Network:
|
|||||||
return self.get_request(method, url, params, headers)
|
return self.get_request(method, url, params, headers)
|
||||||
else:
|
else:
|
||||||
self.refresh_counter = 0
|
self.refresh_counter = 0
|
||||||
logger.critical(f'refresh token limit (5) reached')
|
logger.critical(f'{method} refresh token limit (5) reached')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = req.json().get('error', None)
|
error = req.json().get('error', None)
|
||||||
@ -132,7 +132,7 @@ class Network:
|
|||||||
req = requests.post(const.api_url + url, params=params, json=json, headers=headers)
|
req = requests.post(const.api_url + url, params=params, json=json, headers=headers)
|
||||||
|
|
||||||
if 200 <= req.status_code < 300:
|
if 200 <= req.status_code < 300:
|
||||||
logger.debug(f'{method} post {req.status_code}')
|
logger.debug(f'{method} post {url} {req.status_code}')
|
||||||
return req
|
return req
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ class Network:
|
|||||||
logger.error(f'{method} rate limit reached: cannot find Retry-After header')
|
logger.error(f'{method} rate limit reached: cannot find Retry-After header')
|
||||||
else:
|
else:
|
||||||
self.refresh_counter = 0
|
self.refresh_counter = 0
|
||||||
logger.critical(f'refresh token limit (5) reached')
|
logger.critical(f'{method} refresh token limit (5) reached')
|
||||||
|
|
||||||
elif req.status_code == 401:
|
elif req.status_code == 401:
|
||||||
logger.warning(f'{method} access token expired, refreshing')
|
logger.warning(f'{method} access token expired, refreshing')
|
||||||
@ -159,7 +159,7 @@ class Network:
|
|||||||
return self.post_request(method, url, params, json, headers)
|
return self.post_request(method, url, params, json, headers)
|
||||||
else:
|
else:
|
||||||
self.refresh_counter = 0
|
self.refresh_counter = 0
|
||||||
logger.critical(f'refresh token limit (5) reached')
|
logger.critical(f'{method} refresh token limit (5) reached')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = req.json().get('error', None)
|
error = req.json().get('error', None)
|
||||||
@ -190,7 +190,7 @@ class Network:
|
|||||||
req = requests.put(const.api_url + url, params=params, json=json, headers=headers)
|
req = requests.put(const.api_url + url, params=params, json=json, headers=headers)
|
||||||
|
|
||||||
if 200 <= req.status_code < 300:
|
if 200 <= req.status_code < 300:
|
||||||
logger.debug(f'{method} put {req.status_code}')
|
logger.debug(f'{method} put {url} {req.status_code}')
|
||||||
return req
|
return req
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@ -207,7 +207,7 @@ class Network:
|
|||||||
logger.error(f'{method} rate limit reached: cannot find Retry-After header')
|
logger.error(f'{method} rate limit reached: cannot find Retry-After header')
|
||||||
else:
|
else:
|
||||||
self.refresh_counter = 0
|
self.refresh_counter = 0
|
||||||
logger.critical(f'refresh token limit (5) reached')
|
logger.critical(f'{method} refresh token limit (5) reached')
|
||||||
|
|
||||||
elif req.status_code == 401:
|
elif req.status_code == 401:
|
||||||
logger.warning(f'{method} access token expired, refreshing')
|
logger.warning(f'{method} access token expired, refreshing')
|
||||||
@ -217,7 +217,7 @@ class Network:
|
|||||||
return self.put_request(method, url, params, json, headers)
|
return self.put_request(method, url, params, json, headers)
|
||||||
else:
|
else:
|
||||||
self.refresh_counter = 0
|
self.refresh_counter = 0
|
||||||
logger.critical(f'refresh token limit (5) reached')
|
logger.critical(f'{method} refresh token limit (5) reached')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
error = req.json().get('error', None)
|
error = req.json().get('error', None)
|
||||||
@ -256,12 +256,14 @@ class Network:
|
|||||||
|
|
||||||
if tracks and resp.get('tracks'):
|
if tracks and resp.get('tracks'):
|
||||||
if 'next' in resp['tracks']:
|
if 'next' in resp['tracks']:
|
||||||
|
logger.debug(f'paging tracks for {uri}')
|
||||||
|
|
||||||
track_pager = PageCollection(net=self, page=resp['tracks'])
|
track_pager = PageCollection(net=self, page=resp['tracks'])
|
||||||
track_pager.continue_iteration()
|
track_pager.continue_iteration()
|
||||||
|
|
||||||
playlist.tracks = [self.parse_track(i) for i in track_pager.items]
|
playlist.tracks = [self.parse_track(i) for i in track_pager.items]
|
||||||
else:
|
else:
|
||||||
|
logger.debug(f'parsing {len(resp.get("tracks"))} tracks for {uri}')
|
||||||
playlist.tracks = [self.parse_track(i) for i in resp.get('tracks', [])]
|
playlist.tracks = [self.parse_track(i) for i in resp.get('tracks', [])]
|
||||||
|
|
||||||
return playlist
|
return playlist
|
||||||
@ -284,6 +286,8 @@ class Network:
|
|||||||
:param description: description for new playlist
|
:param description: description for new playlist
|
||||||
:return: newly created playlist object
|
:return: newly created playlist object
|
||||||
"""
|
"""
|
||||||
|
logger.info(f'creating {name} for {username}, '
|
||||||
|
f'public: {public}, collaborative: {collaborative}, description: {description}')
|
||||||
|
|
||||||
json = {"name": name, "public": public, "collaborative": collaborative}
|
json = {"name": name, "public": public, "collaborative": collaborative}
|
||||||
|
|
||||||
@ -305,7 +309,7 @@ class Network:
|
|||||||
:return: List of user created and followed playlists if available
|
:return: List of user created and followed playlists if available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"loading")
|
logger.info(f"paging playlists")
|
||||||
|
|
||||||
pager = PageCollection(net=self, url='me/playlists', name='getPlaylists')
|
pager = PageCollection(net=self, url='me/playlists', name='getPlaylists')
|
||||||
if response_limit:
|
if response_limit:
|
||||||
@ -314,6 +318,9 @@ class Network:
|
|||||||
|
|
||||||
return_items = [self.parse_playlist(i) for i in pager.items]
|
return_items = [self.parse_playlist(i) for i in pager.items]
|
||||||
|
|
||||||
|
if len(return_items) == 0:
|
||||||
|
logger.error('no playlists returned')
|
||||||
|
|
||||||
return return_items
|
return return_items
|
||||||
|
|
||||||
def get_library_albums(self, response_limit: int = None) -> Optional[List[LibraryAlbum]]:
|
def get_library_albums(self, response_limit: int = None) -> Optional[List[LibraryAlbum]]:
|
||||||
@ -323,7 +330,7 @@ class Network:
|
|||||||
:return: List of user library albums if available
|
:return: List of user library albums if available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"loading")
|
logger.info(f"paging library albums")
|
||||||
|
|
||||||
pager = PageCollection(net=self, url='me/albums', name='getLibraryAlbums')
|
pager = PageCollection(net=self, url='me/albums', name='getLibraryAlbums')
|
||||||
if response_limit:
|
if response_limit:
|
||||||
@ -332,6 +339,9 @@ class Network:
|
|||||||
|
|
||||||
return_items = [self.parse_album(i) for i in pager.items]
|
return_items = [self.parse_album(i) for i in pager.items]
|
||||||
|
|
||||||
|
if len(return_items) == 0:
|
||||||
|
logger.error('no albums returned')
|
||||||
|
|
||||||
return return_items
|
return return_items
|
||||||
|
|
||||||
def get_library_tracks(self, response_limit: int = None) -> Optional[List[LibraryTrack]]:
|
def get_library_tracks(self, response_limit: int = None) -> Optional[List[LibraryTrack]]:
|
||||||
@ -341,7 +351,7 @@ class Network:
|
|||||||
:return: List of saved library trakcs if available
|
:return: List of saved library trakcs if available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"loading")
|
logger.info(f"paging library tracks")
|
||||||
|
|
||||||
pager = PageCollection(net=self, url='me/tracks', name='getLibraryTracks')
|
pager = PageCollection(net=self, url='me/tracks', name='getLibraryTracks')
|
||||||
if response_limit:
|
if response_limit:
|
||||||
@ -350,6 +360,9 @@ class Network:
|
|||||||
|
|
||||||
return_items = [self.parse_track(i) for i in pager.items]
|
return_items = [self.parse_track(i) for i in pager.items]
|
||||||
|
|
||||||
|
if len(return_items) == 0:
|
||||||
|
logger.error('no tracks returned')
|
||||||
|
|
||||||
return return_items
|
return return_items
|
||||||
|
|
||||||
def get_user_playlists(self) -> Optional[List[SpotifyPlaylist]]:
|
def get_user_playlists(self) -> Optional[List[SpotifyPlaylist]]:
|
||||||
@ -358,18 +371,18 @@ class Network:
|
|||||||
:return: List of user owned playlists if available
|
:return: List of user owned playlists if available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info('retrieved')
|
logger.info('pulling all playlists')
|
||||||
|
|
||||||
playlists = self.get_playlists()
|
playlists = self.get_playlists()
|
||||||
|
|
||||||
if self.user.username is None:
|
if self.user.username is None:
|
||||||
|
logger.debug('no user info, refreshing for filter')
|
||||||
self.user.refresh_info()
|
self.user.refresh_info()
|
||||||
|
|
||||||
if playlists is not None:
|
if playlists is not None:
|
||||||
return list(filter(lambda x: x.owner.username == self.user.username, playlists))
|
return list(filter(lambda x: x.owner.username == self.user.username, playlists))
|
||||||
else:
|
else:
|
||||||
logger.error('no playlists returned to filter')
|
logger.error('no playlists returned to filter')
|
||||||
return None
|
|
||||||
|
|
||||||
def get_playlist_tracks(self,
|
def get_playlist_tracks(self,
|
||||||
uri: Uri = None,
|
uri: Uri = None,
|
||||||
@ -389,7 +402,7 @@ class Network:
|
|||||||
if uri_string is not None:
|
if uri_string is not None:
|
||||||
uri = Uri(uri_string)
|
uri = Uri(uri_string)
|
||||||
|
|
||||||
logger.info(f"loading")
|
logger.info(f"paging tracks for {uri}")
|
||||||
|
|
||||||
pager = PageCollection(net=self, url=f'playlists/{uri.object_id}/tracks', name='getPlaylistTracks')
|
pager = PageCollection(net=self, url=f'playlists/{uri.object_id}/tracks', name='getPlaylistTracks')
|
||||||
if response_limit:
|
if response_limit:
|
||||||
@ -398,15 +411,20 @@ class Network:
|
|||||||
|
|
||||||
return_items = [self.parse_track(i) for i in pager.items]
|
return_items = [self.parse_track(i) for i in pager.items]
|
||||||
|
|
||||||
|
if len(return_items) == 0:
|
||||||
|
logger.error('no tracks returned')
|
||||||
|
|
||||||
return return_items
|
return return_items
|
||||||
|
|
||||||
def get_available_devices(self) -> Optional[List[Device]]:
|
def get_available_devices(self) -> Optional[List[Device]]:
|
||||||
"""get users available devices"""
|
"""get users available devices"""
|
||||||
|
|
||||||
logger.info("retrieving")
|
logger.info("polling available devices")
|
||||||
|
|
||||||
resp = self.get_request('getAvailableDevices', 'me/player/devices')
|
resp = self.get_request('getAvailableDevices', 'me/player/devices')
|
||||||
if resp:
|
if resp:
|
||||||
|
if len(resp['devices']) == 0:
|
||||||
|
logger.error('no devices returned')
|
||||||
return [self.parse_device(i) for i in resp['devices']]
|
return [self.parse_device(i) for i in resp['devices']]
|
||||||
else:
|
else:
|
||||||
logger.error('no devices returned')
|
logger.error('no devices returned')
|
||||||
@ -424,7 +442,7 @@ class Network:
|
|||||||
:return: list of recently played tracks if available
|
:return: list of recently played tracks if available
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info("retrieving")
|
logger.info(f"paging {'all' if response_limit is None else response_limit} recent tracks ({after}/{before})")
|
||||||
|
|
||||||
params = dict()
|
params = dict()
|
||||||
if after and before:
|
if after and before:
|
||||||
@ -447,19 +465,17 @@ class Network:
|
|||||||
return [self.parse_track(i) for i in pager.items]
|
return [self.parse_track(i) for i in pager.items]
|
||||||
else:
|
else:
|
||||||
logger.error('no tracks returned')
|
logger.error('no tracks returned')
|
||||||
return None
|
|
||||||
|
|
||||||
def get_player(self) -> Optional[CurrentlyPlaying]:
|
def get_player(self) -> Optional[CurrentlyPlaying]:
|
||||||
"""get currently playing snapshot (player)"""
|
"""get currently playing snapshot (player)"""
|
||||||
|
|
||||||
logger.info("retrieved")
|
logger.info("polling player")
|
||||||
|
|
||||||
resp = self.get_request('getPlayer', 'me/player')
|
resp = self.get_request('getPlayer', 'me/player')
|
||||||
if resp:
|
if resp:
|
||||||
return self.parse_currently_playing(resp)
|
return self.parse_currently_playing(resp)
|
||||||
else:
|
else:
|
||||||
logger.info('no player returned')
|
logger.info('no player returned')
|
||||||
return None
|
|
||||||
|
|
||||||
def get_device_id(self, device_name: str) -> Optional[str]:
|
def get_device_id(self, device_name: str) -> Optional[str]:
|
||||||
"""return device id of device as searched for by name
|
"""return device id of device as searched for by name
|
||||||
@ -468,7 +484,7 @@ class Network:
|
|||||||
:return: device ID
|
:return: device ID
|
||||||
"""
|
"""
|
||||||
|
|
||||||
logger.info(f"{device_name}")
|
logger.info(f"querying {device_name}")
|
||||||
|
|
||||||
devices = self.get_available_devices()
|
devices = self.get_available_devices()
|
||||||
if devices:
|
if devices:
|
||||||
@ -490,6 +506,8 @@ class Network:
|
|||||||
'play': True
|
'play': True
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info(f'shifting playback to {device_id}')
|
||||||
|
|
||||||
resp = self.put_request('changePlaybackDevice', 'me/player', json=json)
|
resp = self.put_request('changePlaybackDevice', 'me/player', json=json)
|
||||||
if resp:
|
if resp:
|
||||||
return True
|
return True
|
||||||
@ -630,7 +648,7 @@ class Network:
|
|||||||
if uri_strings is not None:
|
if uri_strings is not None:
|
||||||
uris = [Uri(i) for i in uri_strings]
|
uris = [Uri(i) for i in uri_strings]
|
||||||
|
|
||||||
logger.info(f"{uri}")
|
logger.info(f"replacing {uri} with {'0' if uris is None else len(uris)} tracks")
|
||||||
|
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
@ -655,7 +673,8 @@ class Network:
|
|||||||
collaborative: bool = None,
|
collaborative: bool = None,
|
||||||
description: str = None) -> Optional[Response]:
|
description: str = None) -> Optional[Response]:
|
||||||
|
|
||||||
logger.info(f"{uri}")
|
logger.info(f"updating {uri}, name: {name}, public: {public}, collab: {collaborative}, "
|
||||||
|
f"description: {(description[:30] + '...' if len(description) > 33 else description) if description is not None else None}")
|
||||||
|
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
@ -687,7 +706,7 @@ class Network:
|
|||||||
|
|
||||||
def add_playlist_tracks(self, uri: Uri, uris: List[Uri]) -> List[dict]:
|
def add_playlist_tracks(self, uri: Uri, uris: List[Uri]) -> List[dict]:
|
||||||
|
|
||||||
logger.info(f"{uri}")
|
logger.info(f"adding {len(uris)} tracks to {uri}")
|
||||||
|
|
||||||
headers = {"Content-Type": "application/json"}
|
headers = {"Content-Type": "application/json"}
|
||||||
|
|
||||||
@ -716,7 +735,9 @@ class Network:
|
|||||||
artists: List[SpotifyArtist] = None,
|
artists: List[SpotifyArtist] = None,
|
||||||
response_limit=10) -> Optional[List[Track]]:
|
response_limit=10) -> Optional[List[Track]]:
|
||||||
|
|
||||||
logger.info(f'sample size: {response_limit}')
|
logger.info(f'getting {response_limit} recommendations, '
|
||||||
|
f'tracks: {len(tracks) if tracks is not None else 0}, '
|
||||||
|
f'artists: {len(artists) if artists is not None else 0}')
|
||||||
|
|
||||||
params = {'limit': response_limit}
|
params = {'limit': response_limit}
|
||||||
|
|
||||||
@ -745,9 +766,11 @@ class Network:
|
|||||||
def write_playlist_object(self,
|
def write_playlist_object(self,
|
||||||
playlist: SpotifyPlaylist,
|
playlist: SpotifyPlaylist,
|
||||||
append_tracks: bool = False):
|
append_tracks: bool = False):
|
||||||
|
logger.info(f'writing {playlist.name}, append tracks: {append_tracks}')
|
||||||
|
|
||||||
if playlist.uri:
|
if playlist.uri:
|
||||||
if playlist.tracks == -1:
|
if playlist.tracks == -1:
|
||||||
|
logger.debug(f'wiping {playlist.name} tracks')
|
||||||
self.replace_playlist_tracks(uri=playlist.uri, uris=[])
|
self.replace_playlist_tracks(uri=playlist.uri, uris=[])
|
||||||
elif playlist.tracks:
|
elif playlist.tracks:
|
||||||
if append_tracks:
|
if append_tracks:
|
||||||
@ -773,7 +796,7 @@ class Network:
|
|||||||
range_length: int,
|
range_length: int,
|
||||||
insert_before: int) -> Optional[Response]:
|
insert_before: int) -> Optional[Response]:
|
||||||
|
|
||||||
logger.info(f'id: {uri}')
|
logger.info(f'reordering {uri} tracks, start: {range_start}, length: {range_length}, before: {insert_before}')
|
||||||
|
|
||||||
if range_start < 0:
|
if range_start < 0:
|
||||||
logger.error('range_start must be positive')
|
logger.error('range_start must be positive')
|
||||||
@ -797,7 +820,7 @@ class Network:
|
|||||||
logger.error('error reordering playlist')
|
logger.error('error reordering playlist')
|
||||||
|
|
||||||
def get_track_audio_features(self, uris: List[Uri]):
|
def get_track_audio_features(self, uris: List[Uri]):
|
||||||
logger.info(f'ids: {len(uris)}')
|
logger.info(f'getting {len(uris)} features')
|
||||||
|
|
||||||
audio_features = []
|
audio_features = []
|
||||||
chunked_uris = list(self.chunk(uris, 100))
|
chunked_uris = list(self.chunk(uris, 100))
|
||||||
@ -826,7 +849,7 @@ class Network:
|
|||||||
logger.error('mismatched length of input and response')
|
logger.error('mismatched length of input and response')
|
||||||
|
|
||||||
def populate_track_audio_features(self, tracks=Union[SpotifyTrack, List[SpotifyTrack]]):
|
def populate_track_audio_features(self, tracks=Union[SpotifyTrack, List[SpotifyTrack]]):
|
||||||
logger.info(f'populating')
|
logger.info(f'populating {len(tracks)} features')
|
||||||
|
|
||||||
if isinstance(tracks, SpotifyTrack):
|
if isinstance(tracks, SpotifyTrack):
|
||||||
audio_features = self.get_track_audio_features([tracks.uri])
|
audio_features = self.get_track_audio_features([tracks.uri])
|
||||||
@ -995,6 +1018,8 @@ class Network:
|
|||||||
'limit': response_limit
|
'limit': response_limit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info(f'querying track: {track}, album: {album}, artist: {artist}')
|
||||||
|
|
||||||
resp = self.get_request(method='search', url='search', params=params)
|
resp = self.get_request(method='search', url='search', params=params)
|
||||||
|
|
||||||
albums = [self.parse_album(i) for i in resp.get('albums', {}).get('items', [])]
|
albums = [self.parse_album(i) for i in resp.get('albums', {}).get('items', [])]
|
||||||
@ -1352,7 +1377,7 @@ class PageCollection:
|
|||||||
raise IndexError('no pages')
|
raise IndexError('no pages')
|
||||||
|
|
||||||
def iterate(self, url=None):
|
def iterate(self, url=None):
|
||||||
logger.debug(f'iterating {self.name}')
|
logger.debug(f'iterating {self.name}, {len(self.pages)}/{self.page_limit}')
|
||||||
|
|
||||||
params = {'limit': self.page_limit}
|
params = {'limit': self.page_limit}
|
||||||
if url:
|
if url:
|
||||||
|
Loading…
Reference in New Issue
Block a user