mirror of
				https://github.com/KevinMidboe/spotify-downloader.git
				synced 2025-10-29 18:00:15 +00:00 
			
		
		
		
	Merge options -f and -ff into -f
This commit is contained in:
		@@ -8,7 +8,10 @@ def match_arguments(arguments):
 | 
			
		||||
        for track in arguments.tracks:
 | 
			
		||||
            if track == "-":
 | 
			
		||||
                for line in sys.stdin:
 | 
			
		||||
                    command_line.helpers.download_track(line, arguments)
 | 
			
		||||
                    command_line.helpers.download_track(
 | 
			
		||||
                        line,
 | 
			
		||||
                        arguments
 | 
			
		||||
                    )
 | 
			
		||||
            else:
 | 
			
		||||
                command_line.helpers.download_track(track, arguments)
 | 
			
		||||
    elif arguments.list:
 | 
			
		||||
 
 | 
			
		||||
@@ -136,12 +136,6 @@ def get_arguments(argv=None, to_merge=True):
 | 
			
		||||
        choices={"ffmpeg", "avconv", "null"},
 | 
			
		||||
        help="use this encoder for conversion",
 | 
			
		||||
    )
 | 
			
		||||
    parser.add_argument(
 | 
			
		||||
        "-f",
 | 
			
		||||
        "--directory",
 | 
			
		||||
        default=os.path.abspath(config["directory"]),
 | 
			
		||||
        help="path to directory where downloaded tracks will be stored in",
 | 
			
		||||
    )
 | 
			
		||||
    parser.add_argument(
 | 
			
		||||
        "--overwrite",
 | 
			
		||||
        default=config["overwrite"],
 | 
			
		||||
@@ -175,11 +169,11 @@ def get_arguments(argv=None, to_merge=True):
 | 
			
		||||
        help="write tracks from Spotify playlist, album, etc. to this file",
 | 
			
		||||
    )
 | 
			
		||||
    parser.add_argument(
 | 
			
		||||
        "-ff",
 | 
			
		||||
        "--file-format",
 | 
			
		||||
        default=config["file-format"],
 | 
			
		||||
        help="file format to save the downloaded track with, each tag "
 | 
			
		||||
        "is surrounded by curly braces. Possible formats: "
 | 
			
		||||
        "-f",
 | 
			
		||||
        "--output-file",
 | 
			
		||||
        default=config["output-file"],
 | 
			
		||||
        help="path where to write the downloaded track to, special tags "
 | 
			
		||||
        "are to be surrounded by curly braces. Possible tags: "
 | 
			
		||||
        # "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]),
 | 
			
		||||
    )
 | 
			
		||||
    parser.add_argument(
 | 
			
		||||
@@ -192,8 +186,8 @@ def get_arguments(argv=None, to_merge=True):
 | 
			
		||||
        "-sf",
 | 
			
		||||
        "--search-format",
 | 
			
		||||
        default=config["search-format"],
 | 
			
		||||
        help="search format to search for on YouTube, each tag "
 | 
			
		||||
        "is surrounded by curly braces. Possible formats: "
 | 
			
		||||
        help="search format to search for on YouTube, special tags "
 | 
			
		||||
        "are to be surrounded by curly braces. Possible tags: "
 | 
			
		||||
        # "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]),
 | 
			
		||||
    )
 | 
			
		||||
    parser.add_argument(
 | 
			
		||||
@@ -289,10 +283,10 @@ def get_arguments(argv=None, to_merge=True):
 | 
			
		||||
    if parsed.config is not None and to_merge:
 | 
			
		||||
        parsed = override_config(parsed.config, parser)
 | 
			
		||||
 | 
			
		||||
    return run_errands(parser, parsed)
 | 
			
		||||
    return run_errands(parser, parsed, config)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def run_errands(parser, parsed):
 | 
			
		||||
def run_errands(parser, parsed, config):
 | 
			
		||||
    if (parsed.list
 | 
			
		||||
        and not mimetypes.MimeTypes().guess_type(parsed.list)[0] == "text/plain"
 | 
			
		||||
    ):
 | 
			
		||||
@@ -334,12 +328,23 @@ def run_errands(parser, parsed):
 | 
			
		||||
        setattr(parsed, "tracks", parsed.song)
 | 
			
		||||
    del parsed.song
 | 
			
		||||
 | 
			
		||||
    if parsed.file_format == "-" and parsed.no_metadata is False:
 | 
			
		||||
    if parsed.output_file == "-" and parsed.no_metadata is False:
 | 
			
		||||
        # log.warn(
 | 
			
		||||
        #     "Cannot write metadata when target file is STDOUT. Pass "
 | 
			
		||||
        #     "--no-metadata explicitly to hide this warning."
 | 
			
		||||
        # )
 | 
			
		||||
        parsed.no_metadata = True
 | 
			
		||||
    elif os.path.isdir(parsed.output_file):
 | 
			
		||||
        adjusted_output_file = os.path.join(
 | 
			
		||||
            parsed.output_file,
 | 
			
		||||
            config["output-file"]
 | 
			
		||||
        )
 | 
			
		||||
        # log.warn(
 | 
			
		||||
        #     "Specified output file is a directory. Will write the filename as in
 | 
			
		||||
        #     "default file format. Pass --output-file={} to hide this warning".format(
 | 
			
		||||
        #         adjusted_output_file
 | 
			
		||||
        # )
 | 
			
		||||
        parsed.output_file = adjusted_output_file
 | 
			
		||||
 | 
			
		||||
    parsed.log_level = log_leveller(parsed.log_level)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ from spotdl.metadata.providers import ProviderYouTube
 | 
			
		||||
from spotdl.metadata.providers import YouTubeSearch
 | 
			
		||||
from spotdl.metadata.embedders import EmbedderDefault
 | 
			
		||||
from spotdl.metadata.exceptions import SpotifyMetadataNotFoundError
 | 
			
		||||
import spotdl.metadata
 | 
			
		||||
 | 
			
		||||
from spotdl.encode.encoders import EncoderFFmpeg
 | 
			
		||||
from spotdl.encode.encoders import EncoderAvconv
 | 
			
		||||
@@ -46,17 +47,16 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua
 | 
			
		||||
    if spotdl.util.is_spotify(track):
 | 
			
		||||
        spotify = ProviderSpotify()
 | 
			
		||||
        spotify_metadata = spotify.from_url(track)
 | 
			
		||||
        lyric_query = spotdl.util.format_string(
 | 
			
		||||
        lyric_query = spotdl.metadata.format_string(
 | 
			
		||||
            "{artist} - {track-name}",
 | 
			
		||||
            spotify_metadata,
 | 
			
		||||
        )
 | 
			
		||||
        search_query = spotdl.util.format_string(search_format, spotify_metadata)
 | 
			
		||||
        search_query = spotdl.metadata.format_string(search_format, spotify_metadata)
 | 
			
		||||
        youtube_urls = youtube_searcher.search(search_query)
 | 
			
		||||
        if not youtube_urls:
 | 
			
		||||
            # raise NoYouTubeVideoError(
 | 
			
		||||
            #     'No videos found for the search query: "{}"'.format(search_query)
 | 
			
		||||
            # )
 | 
			
		||||
            return
 | 
			
		||||
            raise NoYouTubeVideoError(
 | 
			
		||||
                'No videos found for the search query: "{}"'.format(search_query)
 | 
			
		||||
            )
 | 
			
		||||
        if manual:
 | 
			
		||||
            pass
 | 
			
		||||
        else:
 | 
			
		||||
@@ -69,7 +69,7 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua
 | 
			
		||||
 | 
			
		||||
    elif spotdl.util.is_youtube(track):
 | 
			
		||||
        metadata = youtube.from_url(track)
 | 
			
		||||
        lyric_query = spotdl.util.format_string(
 | 
			
		||||
        lyric_query = spotdl.metadata.format_string(
 | 
			
		||||
            "{artist} - {track-name}",
 | 
			
		||||
            metadata,
 | 
			
		||||
        )
 | 
			
		||||
@@ -107,11 +107,14 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def download_track(track, arguments):
 | 
			
		||||
    track_splits = track.split(":")
 | 
			
		||||
    if len(track_splits) == 2:
 | 
			
		||||
        youtube_track, spotify_track = track_splits
 | 
			
		||||
    metadata = search_metadata(track, search_format=arguments.search_format)
 | 
			
		||||
    log_fmt = spotdl.util.format_string(
 | 
			
		||||
        arguments.file_format,
 | 
			
		||||
    log_fmt = spotdl.metadata.format_string(
 | 
			
		||||
        arguments.output_file,
 | 
			
		||||
        metadata,
 | 
			
		||||
        output_extension=arguments.output_ext
 | 
			
		||||
        output_extension=arguments.output_ext,
 | 
			
		||||
    )
 | 
			
		||||
    # log.info(log_fmt)
 | 
			
		||||
    download_track_from_metadata(metadata, arguments)
 | 
			
		||||
@@ -119,7 +122,6 @@ def download_track(track, arguments):
 | 
			
		||||
 | 
			
		||||
def download_track_from_metadata(metadata, arguments):
 | 
			
		||||
    # TODO: Add `-m` flag
 | 
			
		||||
 | 
			
		||||
    track = Track(metadata, cache_albumart=(not arguments.no_metadata))
 | 
			
		||||
    print(metadata["name"])
 | 
			
		||||
 | 
			
		||||
@@ -139,11 +141,15 @@ def download_track_from_metadata(metadata, arguments):
 | 
			
		||||
    else:
 | 
			
		||||
        output_extension = arguments.output_ext
 | 
			
		||||
 | 
			
		||||
    filename = spotdl.util.format_string(
 | 
			
		||||
        arguments.file_format,
 | 
			
		||||
    filename = spotdl.metadata.format_string(
 | 
			
		||||
        arguments.output_file,
 | 
			
		||||
        metadata,
 | 
			
		||||
        output_extension=output_extension
 | 
			
		||||
        output_extension=output_extension,
 | 
			
		||||
        sanitizer=lambda s: spotdl.util.sanitize(
 | 
			
		||||
            s, spaces_to_underscores=arguments.no_spaces
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
    print(filename)
 | 
			
		||||
    # log.info(filename)
 | 
			
		||||
 | 
			
		||||
    to_skip = arguments.dry_run
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,6 @@ DEFAULT_CONFIGURATION = {
 | 
			
		||||
        "no-fallback-metadata": False,
 | 
			
		||||
        "avconv": False,
 | 
			
		||||
        "encoder": "ffmpeg",
 | 
			
		||||
        "directory": spotdl.util.get_music_dir(),
 | 
			
		||||
        "overwrite": "prompt",
 | 
			
		||||
        "quality": "best",
 | 
			
		||||
        "input-ext": "automatic",
 | 
			
		||||
@@ -23,7 +22,7 @@ DEFAULT_CONFIGURATION = {
 | 
			
		||||
        "music-videos-only": False,
 | 
			
		||||
        "no-spaces": False,
 | 
			
		||||
        "processor": "synchronous",
 | 
			
		||||
        "file-format": "{artist} - {track-name}.{output-ext}",
 | 
			
		||||
        "output-file": "{artist} - {track-name}.{output-ext}",
 | 
			
		||||
        "search-format": "{artist} - {track-name} lyrics",
 | 
			
		||||
        "youtube-api-key": None,
 | 
			
		||||
        "skip": None,
 | 
			
		||||
 
 | 
			
		||||
@@ -7,3 +7,5 @@ from spotdl.metadata.exceptions import YouTubeMetadataNotFoundError
 | 
			
		||||
 | 
			
		||||
from spotdl.metadata.embedder_base import EmbedderBase
 | 
			
		||||
 | 
			
		||||
from spotdl.metadata.formatter import format_string
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								spotdl/metadata/formatter.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								spotdl/metadata/formatter.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
def format_string(string, metadata, output_extension="", sanitizer=lambda s: s):
 | 
			
		||||
    formats = {
 | 
			
		||||
        "{track-name}"   : metadata["name"],
 | 
			
		||||
        "{artist}"       : metadata["artists"][0]["name"],
 | 
			
		||||
        "{album}"        : metadata["album"]["name"],
 | 
			
		||||
        "{album-artist}" : metadata["artists"][0]["name"],
 | 
			
		||||
        "{genre}"        : metadata["genre"],
 | 
			
		||||
        "{disc-number}"  : metadata["disc_number"],
 | 
			
		||||
        "{duration}"     : metadata["duration"],
 | 
			
		||||
        "{year}"         : metadata["year"],
 | 
			
		||||
        "{original-date}": metadata["release_date"],
 | 
			
		||||
        "{track-number}" : metadata["track_number"],
 | 
			
		||||
        "{total-tracks}" : metadata["total_tracks"],
 | 
			
		||||
        "{isrc}"         : metadata["external_ids"]["isrc"],
 | 
			
		||||
        # TODO: Call `str.zfill` fill on track-id
 | 
			
		||||
        "{track-id}"     : metadata.get("id", ""),
 | 
			
		||||
        "{output-ext}"   : output_extension,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for key, value in formats.items():
 | 
			
		||||
        string = string.replace(key, sanitizer(str(value)))
 | 
			
		||||
 | 
			
		||||
    return string
 | 
			
		||||
 | 
			
		||||
@@ -21,7 +21,7 @@ def test_default_music_directory():
 | 
			
		||||
 | 
			
		||||
@pytest.fixture(scope="module")
 | 
			
		||||
def directory_fixture(tmpdir_factory):
 | 
			
		||||
    dir_path = os.path.join(str(tmpdir_factory.mktemp("tmpdir")), "filter_this_folder")
 | 
			
		||||
    dir_path = os.path.join(str(tmpdir_factory.mktemp("tmpdir")), "filter_this_directory")
 | 
			
		||||
    return dir_path
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,43 +80,15 @@ def is_youtube(raw_song):
 | 
			
		||||
    return status
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def format_string(string, metadata, output_extension=""):
 | 
			
		||||
    formats = {
 | 
			
		||||
        "{track-name}"   : metadata["name"],
 | 
			
		||||
        "{artist}"       : metadata["artists"][0]["name"],
 | 
			
		||||
        "{album}"        : metadata["album"]["name"],
 | 
			
		||||
        "{album-artist}" : metadata["artists"][0]["name"],
 | 
			
		||||
        "{genre}"        : metadata["genre"],
 | 
			
		||||
        "{disc-number}"  : metadata["disc_number"],
 | 
			
		||||
        "{duration}"     : metadata["duration"],
 | 
			
		||||
        "{year}"         : metadata["year"],
 | 
			
		||||
        "{original-date}": metadata["release_date"],
 | 
			
		||||
        "{track-number}" : metadata["track_number"],
 | 
			
		||||
        "{total-tracks}" : metadata["total_tracks"],
 | 
			
		||||
        "{isrc}"         : metadata["external_ids"]["isrc"],
 | 
			
		||||
        # TODO: Call `str.zfill` fill on track-id
 | 
			
		||||
        "{track-id}"     : metadata.get("id", ""),
 | 
			
		||||
        "{output-ext}"   : output_extension,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for key, value in formats.items():
 | 
			
		||||
        string = string.replace(key, str(value))
 | 
			
		||||
 | 
			
		||||
    return string
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def sanitize_title(title, ok="-_()[]{}"):
 | 
			
		||||
def sanitize(string, ok="-_()[]{}", spaces_to_underscores=False):
 | 
			
		||||
    """ Generate filename of the song to be downloaded. """
 | 
			
		||||
 | 
			
		||||
    if const.args.no_spaces:
 | 
			
		||||
        title = title.replace(" ", "_")
 | 
			
		||||
 | 
			
		||||
    # replace slashes with "-" to avoid folder creation errors
 | 
			
		||||
    title = title.replace("/", "-").replace("\\", "-")
 | 
			
		||||
 | 
			
		||||
    if spaces_to_underscores:
 | 
			
		||||
        string = string.replace(" ", "_")
 | 
			
		||||
    # replace slashes with "-" to avoid directory creation errors
 | 
			
		||||
    string = string.replace("/", "-").replace("\\", "-")
 | 
			
		||||
    # slugify removes any special characters
 | 
			
		||||
    title = slugify(title, ok=ok, lower=False, spaces=True)
 | 
			
		||||
    return title
 | 
			
		||||
    string = slugify(string, ok=ok, lower=False, spaces=True)
 | 
			
		||||
    return string
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def filter_path(path):
 | 
			
		||||
@@ -162,7 +134,7 @@ def get_sec(time_str):
 | 
			
		||||
def get_music_dir():
 | 
			
		||||
    home = os.path.expanduser("~")
 | 
			
		||||
 | 
			
		||||
    # On Linux, the localized folder names are the actual ones.
 | 
			
		||||
    # On Linux, the localized directory names are the actual ones.
 | 
			
		||||
    # It's a freedesktop standard though.
 | 
			
		||||
    if sys.platform.startswith("linux"):
 | 
			
		||||
        for file_item in (".config/user-dirs.dirs", "user-dirs.dirs"):
 | 
			
		||||
@@ -176,7 +148,7 @@ def get_music_dir():
 | 
			
		||||
                            )
 | 
			
		||||
 | 
			
		||||
    # Windows / Cygwin
 | 
			
		||||
    # Queries registry for 'My Music' folder path (as this can be changed)
 | 
			
		||||
    # Queries registry for 'My Music' directory path (as this can be changed)
 | 
			
		||||
    if "win" in sys.platform:
 | 
			
		||||
        try:
 | 
			
		||||
            key = winreg.OpenKey(
 | 
			
		||||
@@ -189,7 +161,7 @@ def get_music_dir():
 | 
			
		||||
        except (FileNotFoundError, NameError):
 | 
			
		||||
            pass
 | 
			
		||||
 | 
			
		||||
    # On both Windows and macOS, the localized folder names you see in
 | 
			
		||||
    # On both Windows and macOS, the localized directory names you see in
 | 
			
		||||
    # Explorer and Finder are actually in English on the file system.
 | 
			
		||||
    # So, defaulting to C:\Users\<user>\Music or /Users/<user>/Music
 | 
			
		||||
    # respectively is sufficient.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user