def get_youtube_meta_track(youtube_url: str, spotify_url: str, output_format: str = None): # check if URL is a playlist, user, artist or album, if yes raise an Exception, # else procede # Get the Song Metadata print(f"Gathering Spotify Metadata for: {spotify_url}") raw_track_meta, raw_artist_meta, raw_album_meta = metadata_provider.from_url( spotify_url) song_name = raw_track_meta["name"] contributing_artist = [] for artist in raw_track_meta["artists"]: contributing_artist.append(artist["name"]) converted_file_name = SongObject.create_file_name( song_name, [artist["name"] for artist in raw_track_meta["artists"]]) if output_format is None: output_format = "mp3" converted_file_path = Path(".", f"{converted_file_name}.{output_format}") # if a song is already downloaded skip it if converted_file_path.is_file(): print(f'Skipping "{converted_file_name}" as it\'s already downloaded') return None # (try to) Get lyrics from Genius lyrics = provider_utils._get_song_lyrics(song_name, contributing_artist) return SongObject(raw_track_meta, raw_album_meta, raw_artist_meta, youtube_url, lyrics)
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
def get_song(track): try: song = from_spotify_url( "https://open.spotify.com/track/" + track["track"]["id"], output_format, use_youtube, lyrics_provider, playlist, ) if generate_m3u: file_path = _parse_path_template(path_template, 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["track"]}, {}, {}, None, "", playlist_response ) file_path = _parse_path_template(path_template, song_obj, output_format) return None, f"{file_path}\n" return None, None
def get_youtube_meta_track( youtube_url: str, spotify_url: str, output_format: str = None, lyrics_provider: str = None, ): # check if URL is a playlist, user, artist or album, if yes raise an Exception, # else procede # Get the Song Metadata raw_track_meta, raw_artist_meta, raw_album_meta = metadata_provider.from_url( spotify_url) song_name = raw_track_meta["name"] contributing_artist = [ artist["name"] for artist in raw_track_meta["artists"] ] converted_file_name = SongObject.create_file_name( song_name, [artist["name"] for artist in raw_track_meta["artists"]]) if output_format is None: output_format = "mp3" converted_file_path = Path(".", f"{converted_file_name}.{output_format}") # if a song is already downloaded skip it if converted_file_path.is_file(): print(f'Skipping "{converted_file_name}" as it\'s already downloaded') return None # (try to) Get lyrics from musixmatch/genius # use musixmatch as the default provider if lyrics_provider == "genius": lyrics = lyrics_providers.get_lyrics_genius(song_name, contributing_artist) else: lyrics = lyrics_providers.get_lyrics_musixmatch( song_name, contributing_artist) return SongObject(raw_track_meta, raw_album_meta, raw_artist_meta, youtube_url, lyrics, None)
def from_dump(data_dump: dict) -> SongObject: """ Creates song object from data dump `dict` `data_dump` : data dump used to create song object returns `SongObject` """ raw_track_meta = data_dump["raw_track_meta"] raw_album_meta = data_dump["raw_album_meta"] raw_artist_meta = data_dump["raw_artist_meta"] youtube_link = data_dump["youtube_link"] lyrics = data_dump["lyrics"] return SongObject(raw_track_meta, raw_album_meta, raw_artist_meta, youtube_link, lyrics, None)
def create_song_obj(name: str = None, artists_input: list = None) -> SongObject: if name == None: song_name = "test song" else: song_name = name if artists_input == None: artist_objs = list(map(lambda x: {"name": x}, ["test artist"])) else: artist_objs = list(map(lambda x: {"name": x}, artists_input)) raw_track_meta = { "name": song_name, "album": { "name": "test album", "artists": artist_objs, "release_date": "2021", "images": [{ "url": "https://i.ytimg.com/vi_webp/iqKdEhx-dD4/hqdefault.webp" }], }, "artists": artist_objs, "track_number": "1", "genres": ["test genre"], } raw_album_meta = {"genres": ["test genre"]} raw_artist_meta = {"genres": ["test artist genre"]} return SongObject( raw_track_meta, raw_album_meta, raw_artist_meta, "https://www.youtube.com/watch?v=Th_C95UMegc", "test lyrics", None, )
def from_spotify_url( spotify_url: str, output_format: str = None, use_youtube: bool = False, lyrics_provider: str = None, playlist: dict = None, ) -> SongObject: """ Creates song object using spotfy url `str` `spotify_url` : spotify url used to create song object `str` `output_format` : output format of the song returns a `SongObject` """ # Set default ouput format to mp3 if output_format is None: output_format = "mp3" # Get the Song Metadata raw_track_meta, raw_artist_meta, raw_album_meta = metadata_provider.from_url( spotify_url ) if raw_track_meta is None: raise ValueError("Couldn't get metadata from url") song_name = raw_track_meta["name"] album_name = raw_track_meta["album"]["name"] isrc = raw_track_meta.get("external_ids", {}).get("isrc") duration = round(raw_track_meta["duration_ms"] / 1000, ndigits=3) contributing_artists = [artist["name"] for artist in raw_track_meta["artists"]] display_name = ", ".join(contributing_artists) + " - " + song_name # Create file name converted_file_name = SongObject.create_file_name( song_name, [artist["name"] for artist in raw_track_meta["artists"]] ) # If song name is too long use only first artist if len(converted_file_name) > 250: converted_file_name = SongObject.create_file_name( song_name, [raw_track_meta["artists"][0]["name"]] ) converted_file_path = Path(".", f"{converted_file_name}.{output_format}") # Alternate file path. alternate_file_path = Path(".", f"{display_name}.{output_format}") # if a song is already downloaded skip it if converted_file_path.is_file() or alternate_file_path.is_file(): print(f'Skipping "{converted_file_name}" as it\'s already downloaded') raise OSError(f"{converted_file_name} already downloaded") # Get the song's downloadable audio link if use_youtube: print(f'Searching YouTube for "{display_name}"', end="\r") youtube_link = yt_provider.search_and_get_best_match( song_name, contributing_artists, duration, isrc ) else: print(f'Searching YouTube Music for "{display_name}"', end="\r") youtube_link = ytm_provider.search_and_get_best_match( song_name, contributing_artists, album_name, duration, isrc ) # Check if we found youtube url if youtube_link is None: print( f'Could not match any of the results on YouTube for "{display_name}". Skipping' ) raise LookupError("Could not match any of the results on YouTube for") else: print(" " * (len(display_name) + 25), end="\r") print(f'Found YouTube URL for "{display_name}" : {youtube_link}') # (try to) Get lyrics from musixmatch/genius # use musixmatch as the default provider if lyrics_provider == "genius": lyrics = lyrics_providers.get_lyrics_genius(song_name, contributing_artists) else: lyrics = lyrics_providers.get_lyrics_musixmatch(song_name, contributing_artists) return SongObject( raw_track_meta, raw_album_meta, raw_artist_meta, youtube_link, lyrics, playlist )