def from_url(spotify_url: str): if not ("open.spotify.com" in spotify_url and "track" in spotify_url): raise Exception(f"passed URL is not that of a track: {spotify_url}") # query spotify for song, artist, album details spotify_client = SpotifyClient() raw_track_meta = spotify_client.track(spotify_url) if raw_track_meta is None: raise Exception( "Couldn't get metadata, check if you have passed correct track id") primary_artist_id = raw_track_meta["artists"][0]["id"] raw_artist_meta = spotify_client.artist(primary_artist_id) albumId = raw_track_meta["album"]["id"] raw_album_meta = spotify_client.album(albumId) return raw_track_meta, raw_artist_meta, raw_album_meta
def from_album( album_url: str, output_format: str = None, use_youtube: bool = False, lyrics_provider: str = None, generate_m3u: bool = False, threads: int = 1, path_template: str = None, ) -> List[SongObject]: """ Create and return list containing SongObject for every song in the album `str` `album_url` : Spotify Url of the album whose tracks are to be retrieved `str` `output_format` : output format of the song returns a `list<SongObject>` containing Url's of each track in the given album """ spotify_client = SpotifyClient() tracks = [] album_response = spotify_client.album_tracks(album_url) if album_response is None: raise ValueError("Wrong album id") album_tracks = album_response["items"] # Get all tracks from album while album_response["next"]: album_response = spotify_client.next(album_response) # Failed to get response, break the loop if album_response is None: break album_tracks.extend(album_response["items"]) # Remove songs without id album_tracks = [ track for track in album_tracks if track is not None and track.get("id") is not None ] def get_tracks(track): try: song = from_spotify_url( "https://open.spotify.com/track/" + track["id"], output_format, use_youtube, lyrics_provider, None, ) if generate_m3u: if path_template: file_path = _parse_path_template(path_template, song, output_format) else: file_path = _get_converted_file_path(song, output_format) return song, f"{file_path}\n" return song, None except (LookupError, ValueError): return None, None except OSError: if generate_m3u: song_obj = SongObject(track, album_response, {}, None, "", None) if path_template: file_path = _parse_path_template( path_template, song_obj, output_format ) else: file_path = _get_converted_file_path(song_obj, output_format) return None, f"{file_path}\n" return None, None with concurrent.futures.ThreadPoolExecutor(max_workers=threads) as executor: results = executor.map(get_tracks, album_tracks) album_text = "" for result in results: if result[1] is not None: album_text += result[1] if result[0] is not None and result[0].youtube_link is not None: tracks.append(result[0]) if album_response and generate_m3u is True: album_data = spotify_client.album(album_url) if album_data is not None: album_name = album_data["name"] else: album_name = album_tracks[0]["name"] album_name = format_name(album_name) album_file = Path(f"{album_name}.m3u") with open(album_file, "w", encoding="utf-8") as file: file.write(album_text) return tracks