Implement --manual

This commit is contained in:
Ritiek Malhotra
2020-04-23 22:38:27 +05:30
parent 300f17e5cd
commit 2feb9c4b49
5 changed files with 85 additions and 86 deletions

View File

@@ -4,8 +4,8 @@ from spotdl import command_line
import sys
def match_arguments(arguments):
if arguments.tracks:
for track in arguments.tracks:
if arguments["song"]:
for track in arguments["song"]:
if track == "-":
for line in sys.stdin:
command_line.helpers.download_track(
@@ -14,36 +14,36 @@ def match_arguments(arguments):
)
else:
command_line.helpers.download_track(track, arguments)
elif arguments.list:
if arguments.write_m3u:
elif arguments["list"]:
if arguments["write_m3u"]:
youtube_tools.generate_m3u(
track_file=arguments.list
track_file=arguments["list"]
)
else:
list_download = {
"sequential": command_line.helpers.download_tracks_from_file,
"threaded" : command_line.helpers.download_tracks_from_file_threaded,
}[arguments.processor]
}[arguments["processor"]]
list_download(
arguments.list,
arguments["list"],
arguments,
)
elif arguments.playlist:
elif arguments["playlist"]:
spotify_tools.write_playlist(
playlist_url=arguments.playlist, text_file=arguments.write_to
playlist_url=arguments["playlist"], text_file=arguments["write_to"]
)
elif arguments.album:
elif arguments["album"]:
spotify_tools.write_album(
album_url=arguments.album, text_file=arguments.write_to
album_url=arguments["album"], text_file=arguments["write_to"]
)
elif arguments.all_albums:
spotify_tools.write_all_albums_from_artist(
artist_url=arguments.all_albums, text_file=arguments.write_to
artist_url=arguments["all_albums"], text_file=arguments["write_to"]
)
elif arguments.username:
spotify_tools.write_user_playlist(
username=arguments.username, text_file=arguments.write_to
username=arguments["username"], text_file=arguments["write_to"]
)
@@ -59,7 +59,7 @@ def main():
# logzero.setup_default_logger(formatter=const._formatter, level=const.args.log_level)
try:
match_arguments(arguments)
match_arguments(arguments.__dict__)
except KeyboardInterrupt as e:
# log.exception(e)
sys.exit(2)

View File

@@ -51,18 +51,10 @@ def get_arguments(argv=None, to_merge=True):
group = parser.add_mutually_exclusive_group(required=True)
# TODO: --song is deprecated. Remove in future versions.
# Use --tracks instead.
group.add_argument(
"-s",
"--song",
nargs="+",
help=argparse.SUPPRESS
)
group.add_argument(
"-t",
"--tracks",
nargs="+",
help="download track(s) by spotify link or name"
)
group.add_argument(
@@ -115,13 +107,6 @@ def get_arguments(argv=None, to_merge=True):
help="do not embed metadata in tracks",
action="store_true",
)
parser.add_argument(
"-nf",
"--no-fallback-metadata",
default=config["no-fallback-metadata"],
help="do not use YouTube as fallback for metadata if track not found on Spotify",
action="store_true",
)
parser.add_argument(
"-a",
"--avconv",
@@ -190,13 +175,6 @@ def get_arguments(argv=None, to_merge=True):
"are to be surrounded by curly braces. Possible tags: "
# "{}".format([spotdl.util.formats[x] for x in spotdl.util.formats]),
)
parser.add_argument(
"-dm",
"--download-only-metadata",
default=config["download-only-metadata"],
help="download tracks only whose metadata is found",
action="store_true",
)
parser.add_argument(
"-d",
"--dry-run",
@@ -210,15 +188,17 @@ def get_arguments(argv=None, to_merge=True):
"--music-videos-only",
default=config["music-videos-only"],
help="search only for music videos on Youtube (works only "
"when YouTube API key is set",
"when YouTube API key is set)",
action="store_true",
)
parser.add_argument(
"--processor",
default=config["processor"],
choices={"synchronous", "threaded"},
help='list downloading strategy: - "synchronous" downloads '
'tracks one-by-one. - "threaded" (highly experimental!) pre-fetches '
'the next track\'s metadata for more efficient downloading'
'tracks one-by-one. - "threaded" (highly experimental at the '
'moment! expect it to slash & burn) pre-fetches the next '
'track\'s metadata for more efficient downloading'
)
parser.add_argument(
"-ns",
@@ -321,13 +301,6 @@ def run_errands(parser, parsed, config):
# "output format".format(parsed.encoder))
parsed.encoder = "null"
song_parameter_passed = parsed.song is not None and parsed.tracks is None
if song_parameter_passed:
# log.warn("-s / --song is deprecated and will be removed in future versions. "
# "Use -t / --tracks instead.")
setattr(parsed, "tracks", parsed.song)
del parsed.song
if parsed.output_file == "-" and parsed.no_metadata is False:
# log.warn(
# "Cannot write metadata when target file is STDOUT. Pass "

View File

@@ -40,7 +40,23 @@ def search_metadata_on_spotify(query):
return metadata
def prompt_for_youtube_search_result(videos):
urls = []
print("0. Skip downloading this track")
for index, video in enumerate(videos, 1):
video_repr = "{index}. {title} [{duration}] ({url})".format(
index=index,
title=video["title"],
duration=video["duration"],
url=video["url"]
)
print(video_repr)
urls.append(video["url"])
return spotdl.util.prompt_user_for_selection(urls)
def search_metadata(track, search_format="{artist} - {track-name} lyrics", manual=False):
# TODO: Clean this function
youtube = ProviderYouTube()
youtube_searcher = YouTubeSearch()
@@ -52,16 +68,16 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua
spotify_metadata,
)
search_query = spotdl.metadata.format_string(search_format, spotify_metadata)
youtube_urls = youtube_searcher.search(search_query)
if not youtube_urls:
youtube_videos = youtube_searcher.search(search_query)
if not youtube_videos:
raise NoYouTubeVideoError(
'No videos found for the search query: "{}"'.format(search_query)
)
if manual:
pass
youtube_video = prompt_for_youtube_search_result(youtube_videos)
else:
youtube_url = youtube_urls.bestmatch()["url"]
youtube_metadata = youtube.from_url(youtube_url)
youtube_video = youtube_videos.bestmatch()["url"]
youtube_metadata = youtube.from_url(youtube_video)
metadata = spotdl.util.merge(
youtube_metadata,
spotify_metadata
@@ -81,17 +97,17 @@ def search_metadata(track, search_format="{artist} - {track-name} lyrics", manua
args=(track,)
)
spotify_metadata.start()
youtube_urls = youtube_searcher.search(track)
if not youtube_urls:
# raise NoYouTubeVideoError(
# 'No videos found for the search query: "{}"'.format(track)
# )
youtube_videos = youtube_searcher.search(track)
if not youtube_videos:
raise NoYouTubeVideoError(
'No videos found for the search query: "{}"'.format(track)
)
return
if manual:
pass
youtube_video = prompt_for_youtube_search_result(youtube_videos)
else:
youtube_url = youtube_urls.bestmatch()["url"]
youtube_metadata = youtube.from_url(youtube_url)
youtube_video = youtube_videos.bestmatch()["url"]
youtube_metadata = youtube.from_url(youtube_video)
metadata = spotdl.util.merge(
youtube_metadata,
spotify_metadata.join()
@@ -110,11 +126,15 @@ 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"],
manual=arguments["manual"],
)
log_fmt = spotdl.metadata.format_string(
arguments.output_file,
arguments["output_file"],
metadata,
output_extension=arguments.output_ext,
output_extension=arguments["output_ext"],
)
# log.info(log_fmt)
download_track_from_metadata(metadata, arguments)
@@ -122,41 +142,41 @@ 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))
track = Track(metadata, cache_albumart=(not arguments["no_metadata"]))
print(metadata["name"])
stream = metadata["streams"].get(
quality=arguments.quality,
preftype=arguments.input_ext,
quality=arguments["quality"],
preftype=arguments["input_ext"],
)
# log.info(stream)
Encoder = {
"ffmpeg": EncoderFFmpeg,
"avconv": EncoderAvconv,
}.get(arguments.encoder)
}.get(arguments["encoder"])
if Encoder is None:
output_extension = stream["encoding"]
else:
output_extension = arguments.output_ext
output_extension = arguments["output_ext"]
filename = spotdl.metadata.format_string(
arguments.output_file,
arguments["output_file"],
metadata,
output_extension=output_extension,
sanitizer=lambda s: spotdl.util.sanitize(
s, spaces_to_underscores=arguments.no_spaces
s, spaces_to_underscores=arguments["no_spaces"]
)
)
print(filename)
# log.info(filename)
to_skip = arguments.dry_run
to_skip = arguments["dry_run"]
if not to_skip and os.path.isfile(filename):
if arguments.overwrite == "force":
if arguments["overwrite"] == "force":
to_skip = False
elif arguments.overwrite == "prompt":
elif arguments["overwrite"] == "prompt":
to_skip = not input("overwrite? (y/N)").lower() == "y"
else:
to_skip = True
@@ -174,7 +194,7 @@ def download_track_from_metadata(metadata, arguments):
encoder=Encoder()
)
if not arguments.no_metadata:
if not arguments["no_metadata"]:
track.metadata["lyrics"] = track.metadata["lyrics"].join()
try:
track.apply_metadata(filename, encoding=output_extension)
@@ -206,7 +226,7 @@ def download_tracks_from_file(path, arguments):
for number, track in enumerate(tracks, 1):
try:
metadata = search_metadata(next_track, arguments.search_format)
metadata = search_metadata(next_track, arguments["search_format"])
log_fmt=(str(number) + ". {artist} - {track-name}")
# log.info(log_fmt)
download_track_from_metadata(metadata, arguments)
@@ -215,8 +235,8 @@ def download_tracks_from_file(path, arguments):
# log.warning("Failed. Will retry after other songs\n")
tracks.append(track)
else:
if arguments.write_sucessful:
with open(arguments.write_successful, "a") as fout:
if arguments["write_sucessful"]:
with open(arguments["write_successful"], "a") as fout:
fout.write(track)
finally:
with open(path, "w") as fout:
@@ -254,7 +274,7 @@ def download_tracks_from_file_threaded(path, arguments):
"current_track": None,
"next_track": spotdl.util.ThreadWithReturnValue(
target=search_metadata,
args=(next_track, arguments.search_format)
args=(next_track, arguments["search_format"])
)
}
metadata["next_track"].start()
@@ -269,7 +289,7 @@ def download_tracks_from_file_threaded(path, arguments):
next_track = tracks.pop(0)
metadata["next_track"] = spotdl.util.ThreadWithReturnValue(
target=search_metadata,
args=(next_track, arguments.search_format)
args=(next_track, arguments["search_format"])
)
metadata["next_track"].start()
@@ -289,8 +309,8 @@ def download_tracks_from_file_threaded(path, arguments):
tracks.append(current_track)
else:
tracks_count -= 1
if arguments.write_successful:
with open(arguments.write_successful, "a") as fout:
if arguments["write_successful"]:
with open(arguments["write_successful"], "a") as fout:
fout.write(current_track)
finally:
current_iteration += 1

View File

@@ -20,6 +20,9 @@ class YouTubeVideos(Sequence):
self.videos = videos
super().__init__()
def __repr__(self):
return "YouTubeVideos({})".format(self.videos)
def __len__(self):
return len(self.videos)

View File

@@ -49,20 +49,23 @@ def merge(base, overrider):
return merger
def input_link(links):
def prompt_user_for_selection(items):
""" Let the user input a choice. """
while True:
try:
log.info("Choose your number:")
# log.info("Choose your number:")
print("Choose your number:")
the_chosen_one = int(input("> "))
if 1 <= the_chosen_one <= len(links):
return links[the_chosen_one - 1]
if 1 <= the_chosen_one <= len(items):
return items[the_chosen_one - 1]
elif the_chosen_one == 0:
return None
else:
log.warning("Choose a valid number!")
# log.warning("Choose a valid number!")
print("Chose a valid number!")
except ValueError:
log.warning("Choose a valid number!")
# log.warning("Choose a valid number!")
print("Chose a valid number!")
def is_spotify(raw_song):