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: |         for track in arguments.tracks: | ||||||
|             if track == "-": |             if track == "-": | ||||||
|                 for line in sys.stdin: |                 for line in sys.stdin: | ||||||
|                     command_line.helpers.download_track(line, arguments) |                     command_line.helpers.download_track( | ||||||
|  |                         line, | ||||||
|  |                         arguments | ||||||
|  |                     ) | ||||||
|             else: |             else: | ||||||
|                 command_line.helpers.download_track(track, arguments) |                 command_line.helpers.download_track(track, arguments) | ||||||
|     elif arguments.list: |     elif arguments.list: | ||||||
|   | |||||||
| @@ -136,12 +136,6 @@ def get_arguments(argv=None, to_merge=True): | |||||||
|         choices={"ffmpeg", "avconv", "null"}, |         choices={"ffmpeg", "avconv", "null"}, | ||||||
|         help="use this encoder for conversion", |         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( |     parser.add_argument( | ||||||
|         "--overwrite", |         "--overwrite", | ||||||
|         default=config["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", |         help="write tracks from Spotify playlist, album, etc. to this file", | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
|         "-ff", |         "-f", | ||||||
|         "--file-format", |         "--output-file", | ||||||
|         default=config["file-format"], |         default=config["output-file"], | ||||||
|         help="file format to save the downloaded track with, each tag " |         help="path where to write the downloaded track to, special tags " | ||||||
|         "is surrounded by curly braces. Possible formats: " |         "are to be surrounded by curly braces. Possible tags: " | ||||||
|         # "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]), |         # "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]), | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
| @@ -192,8 +186,8 @@ def get_arguments(argv=None, to_merge=True): | |||||||
|         "-sf", |         "-sf", | ||||||
|         "--search-format", |         "--search-format", | ||||||
|         default=config["search-format"], |         default=config["search-format"], | ||||||
|         help="search format to search for on YouTube, each tag " |         help="search format to search for on YouTube, special tags " | ||||||
|         "is surrounded by curly braces. Possible formats: " |         "are to be surrounded by curly braces. Possible tags: " | ||||||
|         # "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]), |         # "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]), | ||||||
|     ) |     ) | ||||||
|     parser.add_argument( |     parser.add_argument( | ||||||
| @@ -289,10 +283,10 @@ def get_arguments(argv=None, to_merge=True): | |||||||
|     if parsed.config is not None and to_merge: |     if parsed.config is not None and to_merge: | ||||||
|         parsed = override_config(parsed.config, parser) |         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 |     if (parsed.list | ||||||
|         and not mimetypes.MimeTypes().guess_type(parsed.list)[0] == "text/plain" |         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) |         setattr(parsed, "tracks", parsed.song) | ||||||
|     del 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( |         # log.warn( | ||||||
|         #     "Cannot write metadata when target file is STDOUT. Pass " |         #     "Cannot write metadata when target file is STDOUT. Pass " | ||||||
|         #     "--no-metadata explicitly to hide this warning." |         #     "--no-metadata explicitly to hide this warning." | ||||||
|         # ) |         # ) | ||||||
|         parsed.no_metadata = True |         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) |     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.providers import YouTubeSearch | ||||||
| from spotdl.metadata.embedders import EmbedderDefault | from spotdl.metadata.embedders import EmbedderDefault | ||||||
| from spotdl.metadata.exceptions import SpotifyMetadataNotFoundError | from spotdl.metadata.exceptions import SpotifyMetadataNotFoundError | ||||||
|  | import spotdl.metadata | ||||||
|  |  | ||||||
| from spotdl.encode.encoders import EncoderFFmpeg | from spotdl.encode.encoders import EncoderFFmpeg | ||||||
| from spotdl.encode.encoders import EncoderAvconv | 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): |     if spotdl.util.is_spotify(track): | ||||||
|         spotify = ProviderSpotify() |         spotify = ProviderSpotify() | ||||||
|         spotify_metadata = spotify.from_url(track) |         spotify_metadata = spotify.from_url(track) | ||||||
|         lyric_query = spotdl.util.format_string( |         lyric_query = spotdl.metadata.format_string( | ||||||
|             "{artist} - {track-name}", |             "{artist} - {track-name}", | ||||||
|             spotify_metadata, |             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) |         youtube_urls = youtube_searcher.search(search_query) | ||||||
|         if not youtube_urls: |         if not youtube_urls: | ||||||
|             # raise NoYouTubeVideoError( |             raise NoYouTubeVideoError( | ||||||
|             #     'No videos found for the search query: "{}"'.format(search_query) |                 'No videos found for the search query: "{}"'.format(search_query) | ||||||
|             # ) |             ) | ||||||
|             return |  | ||||||
|         if manual: |         if manual: | ||||||
|             pass |             pass | ||||||
|         else: |         else: | ||||||
| @@ -69,7 +69,7 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua | |||||||
|  |  | ||||||
|     elif spotdl.util.is_youtube(track): |     elif spotdl.util.is_youtube(track): | ||||||
|         metadata = youtube.from_url(track) |         metadata = youtube.from_url(track) | ||||||
|         lyric_query = spotdl.util.format_string( |         lyric_query = spotdl.metadata.format_string( | ||||||
|             "{artist} - {track-name}", |             "{artist} - {track-name}", | ||||||
|             metadata, |             metadata, | ||||||
|         ) |         ) | ||||||
| @@ -107,11 +107,14 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua | |||||||
|  |  | ||||||
|  |  | ||||||
| def download_track(track, arguments): | 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) |     metadata = search_metadata(track, search_format=arguments.search_format) | ||||||
|     log_fmt = spotdl.util.format_string( |     log_fmt = spotdl.metadata.format_string( | ||||||
|         arguments.file_format, |         arguments.output_file, | ||||||
|         metadata, |         metadata, | ||||||
|         output_extension=arguments.output_ext |         output_extension=arguments.output_ext, | ||||||
|     ) |     ) | ||||||
|     # log.info(log_fmt) |     # log.info(log_fmt) | ||||||
|     download_track_from_metadata(metadata, arguments) |     download_track_from_metadata(metadata, arguments) | ||||||
| @@ -119,7 +122,6 @@ def download_track(track, arguments): | |||||||
|  |  | ||||||
| def download_track_from_metadata(metadata, arguments): | def download_track_from_metadata(metadata, arguments): | ||||||
|     # TODO: Add `-m` flag |     # TODO: Add `-m` flag | ||||||
|  |  | ||||||
|     track = Track(metadata, cache_albumart=(not arguments.no_metadata)) |     track = Track(metadata, cache_albumart=(not arguments.no_metadata)) | ||||||
|     print(metadata["name"]) |     print(metadata["name"]) | ||||||
|  |  | ||||||
| @@ -139,11 +141,15 @@ def download_track_from_metadata(metadata, arguments): | |||||||
|     else: |     else: | ||||||
|         output_extension = arguments.output_ext |         output_extension = arguments.output_ext | ||||||
|  |  | ||||||
|     filename = spotdl.util.format_string( |     filename = spotdl.metadata.format_string( | ||||||
|         arguments.file_format, |         arguments.output_file, | ||||||
|         metadata, |         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) |     # log.info(filename) | ||||||
|  |  | ||||||
|     to_skip = arguments.dry_run |     to_skip = arguments.dry_run | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ DEFAULT_CONFIGURATION = { | |||||||
|         "no-fallback-metadata": False, |         "no-fallback-metadata": False, | ||||||
|         "avconv": False, |         "avconv": False, | ||||||
|         "encoder": "ffmpeg", |         "encoder": "ffmpeg", | ||||||
|         "directory": spotdl.util.get_music_dir(), |  | ||||||
|         "overwrite": "prompt", |         "overwrite": "prompt", | ||||||
|         "quality": "best", |         "quality": "best", | ||||||
|         "input-ext": "automatic", |         "input-ext": "automatic", | ||||||
| @@ -23,7 +22,7 @@ DEFAULT_CONFIGURATION = { | |||||||
|         "music-videos-only": False, |         "music-videos-only": False, | ||||||
|         "no-spaces": False, |         "no-spaces": False, | ||||||
|         "processor": "synchronous", |         "processor": "synchronous", | ||||||
|         "file-format": "{artist} - {track-name}.{output-ext}", |         "output-file": "{artist} - {track-name}.{output-ext}", | ||||||
|         "search-format": "{artist} - {track-name} lyrics", |         "search-format": "{artist} - {track-name} lyrics", | ||||||
|         "youtube-api-key": None, |         "youtube-api-key": None, | ||||||
|         "skip": None, |         "skip": None, | ||||||
|   | |||||||
| @@ -7,3 +7,5 @@ from spotdl.metadata.exceptions import YouTubeMetadataNotFoundError | |||||||
|  |  | ||||||
| from spotdl.metadata.embedder_base import EmbedderBase | 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") | @pytest.fixture(scope="module") | ||||||
| def directory_fixture(tmpdir_factory): | 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 |     return dir_path | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -80,43 +80,15 @@ def is_youtube(raw_song): | |||||||
|     return status |     return status | ||||||
|  |  | ||||||
|  |  | ||||||
| def format_string(string, metadata, output_extension=""): | def sanitize(string, ok="-_()[]{}", spaces_to_underscores=False): | ||||||
|     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="-_()[]{}"): |  | ||||||
|     """ Generate filename of the song to be downloaded. """ |     """ Generate filename of the song to be downloaded. """ | ||||||
|  |     if spaces_to_underscores: | ||||||
|     if const.args.no_spaces: |         string = string.replace(" ", "_") | ||||||
|         title = title.replace(" ", "_") |     # replace slashes with "-" to avoid directory creation errors | ||||||
|  |     string = string.replace("/", "-").replace("\\", "-") | ||||||
|     # replace slashes with "-" to avoid folder creation errors |  | ||||||
|     title = title.replace("/", "-").replace("\\", "-") |  | ||||||
|  |  | ||||||
|     # slugify removes any special characters |     # slugify removes any special characters | ||||||
|     title = slugify(title, ok=ok, lower=False, spaces=True) |     string = slugify(string, ok=ok, lower=False, spaces=True) | ||||||
|     return title |     return string | ||||||
|  |  | ||||||
|  |  | ||||||
| def filter_path(path): | def filter_path(path): | ||||||
| @@ -162,7 +134,7 @@ def get_sec(time_str): | |||||||
| def get_music_dir(): | def get_music_dir(): | ||||||
|     home = os.path.expanduser("~") |     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. |     # It's a freedesktop standard though. | ||||||
|     if sys.platform.startswith("linux"): |     if sys.platform.startswith("linux"): | ||||||
|         for file_item in (".config/user-dirs.dirs", "user-dirs.dirs"): |         for file_item in (".config/user-dirs.dirs", "user-dirs.dirs"): | ||||||
| @@ -176,7 +148,7 @@ def get_music_dir(): | |||||||
|                             ) |                             ) | ||||||
|  |  | ||||||
|     # Windows / Cygwin |     # 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: |     if "win" in sys.platform: | ||||||
|         try: |         try: | ||||||
|             key = winreg.OpenKey( |             key = winreg.OpenKey( | ||||||
| @@ -189,7 +161,7 @@ def get_music_dir(): | |||||||
|         except (FileNotFoundError, NameError): |         except (FileNotFoundError, NameError): | ||||||
|             pass |             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. |     # Explorer and Finder are actually in English on the file system. | ||||||
|     # So, defaulting to C:\Users\<user>\Music or /Users/<user>/Music |     # So, defaulting to C:\Users\<user>\Music or /Users/<user>/Music | ||||||
|     # respectively is sufficient. |     # respectively is sufficient. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user