Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a no-overwrites option that avoids re-downloading a song if it already exists locally #219

Merged
merged 7 commits into from
Jan 17, 2022
6 changes: 5 additions & 1 deletion spotify_dl/spotify_dl.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def spotify_dl():
help='Don\'t convert downloaded songs to mp3')
parser.add_argument('-s', '--scrape', action="store",
help="Use HTML Scraper for YouTube Search", default=True)
parser.add_argument('-w', '--no-overwrites', action='store_true',
help="Whether we should avoid overwriting the target audio file if it already exists",
default=False)
parser.add_argument('-V', '--verbose', action='store_true',
help='Show more information on what''s happening.')
parser.add_argument('-v', '--version', action='store_true',
Expand Down Expand Up @@ -88,7 +91,8 @@ def spotify_dl():
if args.keep_playlist_order:
file_name_f = playlist_num_filename

download_songs(songs, save_path, args.format_str, args.skip_mp3, args.keep_playlist_order, file_name_f)
download_songs(songs, save_path, args.format_str, args.skip_mp3, args.keep_playlist_order, args.no_overwrites,
file_name_f)


if __name__ == '__main__':
Expand Down
57 changes: 35 additions & 22 deletions spotify_dl/youtube.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@ def playlist_num_filename(song):


def download_songs(songs, download_directory, format_string, skip_mp3,
keep_playlist_order=False, file_name_f=default_filename):
keep_playlist_order=False, no_overwrites=False, file_name_f=default_filename):
"""
Downloads songs from the YouTube URL passed to either current directory or download_directory, is it is passed.
:param songs: Dictionary of songs and associated artist
:param download_directory: Location where to save
:param format_string: format string for the file conversion
:param skip_mp3: Whether to skip conversion to MP3
:param keep_playlist_order: Whether to keep original playlist ordering. Also, prefixes songs files with playlist num
:param no_overwrites: Whether we should avoid overwriting the song if it already exists
:param file_name_f: optional func(song) -> str that returns a filename for the download (without extension)
"""
overwrites = not no_overwrites
log.debug(f"Downloading to {download_directory}")
for song in songs:
query = f"{song.get('artist')} - {song.get('name')} Lyrics".replace(":", "").replace("\"", "")
Expand Down Expand Up @@ -66,25 +68,36 @@ def download_songs(songs, download_directory, format_string, skip_mp3,
continue

if not skip_mp3:
try:
song_file = MP3(path.join(f"{file_path}.mp3"), ID3=EasyID3)
except mutagen.MutagenError as e:
log.debug(e)
print('Failed to download: {}, please ensure YouTubeDL is up-to-date. '.format(query))
continue
song_file['date'] = song.get('year')
if keep_playlist_order:
song_file['tracknumber'] = str(song.get('playlist_num'))
mp3filename = f"{file_path}.mp3"
mp3file_path = path.join(mp3filename)
if overwrites or not path.exists(mp3file_path):
try:
song_file = MP3(mp3file_path, ID3=EasyID3)
except mutagen.MutagenError as e:
log.debug(e)
print('Failed to download: {}, please ensure YouTubeDL is up-to-date. '.format(query))
continue
song_file['date'] = song.get('year')
if keep_playlist_order:
song_file['tracknumber'] = str(song.get('playlist_num'))
else:
song_file['tracknumber'] = str(song.get('num')) + '/' + str(song.get('num_tracks'))
song_file['genre'] = song.get('genre')
song_file.save()
song_file = MP3(mp3filename, ID3=ID3)
cover = song.get('cover')
if cover is not None:
if cover.lower().startswith('http'):
req = urllib.request.Request(cover)
else:
raise ValueError from None
with urllib.request.urlopen(req) as resp: # nosec
song_file.tags['APIC'] = APIC(
encoding=3,
mime='image/jpeg',
type=3, desc=u'Cover',
data=resp.read()
)
song_file.save()
else:
song_file['tracknumber'] = str(song.get('num')) + '/' + str(song.get('num_tracks'))
song_file['genre'] = song.get('genre')
song_file.save()
song_file = MP3(f"{file_path}.mp3", ID3=ID3)
if song.get('cover') is not None:
song_file.tags['APIC'] = APIC(
encoding=3,
mime='image/jpeg',
type=3, desc=u'Cover',
data=urllib.request.urlopen(song.get('cover')).read()
)
song_file.save()
print('File {} already exists, we do not overwrite it '.format(mp3filename))