summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xjamos251
1 files changed, 157 insertions, 94 deletions
diff --git a/jamos b/jamos
index 8442eae..dd0a5a0 100755
--- a/jamos
+++ b/jamos
@@ -1,7 +1,6 @@
#!/usr/bin/env python3
import argparse
import collections
-import datetime
import glob
import json
import music_tag
@@ -37,6 +36,17 @@ How the albums will be formatted:
"""
ALBUMS = collections.defaultdict(lambda: None)
+# Array to save any failed songs and their reasons
+FAILED_SONGS = []
+
+
+class UnableToCreateAlbumDirectoryError(Exception):
+ pass
+
+
+class UnableToFindThumbnailFileError(Exception):
+ pass
+
def get_command_line_options():
parser = argparse.ArgumentParser(
@@ -211,9 +221,9 @@ def save_album(app, args, album_id):
with open(filename, 'wb') as f:
shutil.copyfileobj(r.raw, f)
- print('Image sucessfully Downloaded: ', filename)
+ print('Thumbnail sucessfully Downloaded: {}'.format(filename))
else:
- print('Image Couldn\'t be retreived')
+ print('Thumbnail could not be retrieved: {}'.format(filename))
parsed_album['thumbnail_filepath'] = filename
except Exception as ex:
@@ -282,58 +292,58 @@ def get_library_songs(app, args, order='a_to_z'):
return all_parsed_songs
-def stuff():
- # TODO: Can you use the cookies from YTMusic here
- # cookies = os.path.join(os.path.expanduser("~"), "cookies.txt")
- cookies = './cookies.txt'
- ytdl = create_downloader(music_directory, cookies)
-
- failed_songs = []
- for song in []:
- try:
- ytdl.extract_info(song['url'], download=True)
- except Exception as ex:
- print(ex)
- print("Could not download: {}".format((song)))
- failed_songs.append(song)
-
- failed_songs = []
-
- for song in all_songs:
- try:
- print("Downloading: {} - {} - {} from {}...".format(
- song['title'], song['artist'], song['album'], song['url']),
- end='')
- ytdl.extract_info(song['url'], download=True)
- sys.exit()
- print("Done.")
- except Exception as ex:
- print(ex)
- print("Could not download: {}".format((song['url'])))
- failed_songs.append(song)
-
- files = get_all_files(music_directory)
-
- counter = 1
- for f in files:
- try:
- print("Adding metadata to {} ...".format(f), end="")
- with open(f.replace('.mp3', '.info.json')) as json_file:
- json_data = json.load(json_file)
- metadata = get_song_metadata_from_json(json_data, counter)
- write_metadata_to_song_file(f, metadata)
- print("Done")
- print("Moving file...", end="")
- move_file(f, metadata, music_directory)
- print("Done")
- counter += 1
- except Exception as e:
- # just gonna print this and move on to the next file.
- print(e)
-
- print("Cleaning up JSON files...", end='')
- cleanup_metadata_files(music_directory)
- print("Done.")
+# def stuff():
+# # TODO: Can you use the cookies from YTMusic here
+# # cookies = os.path.join(os.path.expanduser("~"), "cookies.txt")
+# cookies = './cookies.txt'
+# ytdl = create_downloader(music_directory, cookies)
+
+# failed_songs = []
+# for song in []:
+# try:
+# ytdl.extract_info(song['url'], download=True)
+# except Exception as ex:
+# print(ex)
+# print("Could not download: {}".format((song)))
+# failed_songs.append(song)
+
+# failed_songs = []
+
+# for song in songs:
+# try:
+# print("Downloading: {} - {} - {} from {}...".format(
+# song['title'], song['artist'], song['album'], song['url']),
+# end='')
+# ytdl.extract_info(song['url'], download=True)
+# sys.exit()
+# print("Done.")
+# except Exception as ex:
+# print(ex)
+# print("Could not download: {}".format((song['url'])))
+# failed_songs.append(song)
+
+# files = get_all_files(music_directory)
+
+# counter = 1
+# for f in files:
+# try:
+# print("Adding metadata to {} ...".format(f), end="")
+# with open(f.replace('.mp3', '.info.json')) as json_file:
+# json_data = json.load(json_file)
+# metadata = get_song_metadata_from_json(json_data, counter)
+# write_metadata_to_song_file(f, metadata)
+# print("Done")
+# print("Moving file...", end="")
+# move_file(f, metadata, music_directory)
+# print("Done")
+# counter += 1
+# except Exception as e:
+# # just gonna print this and move on to the next file.
+# print(e)
+
+# print("Cleaning up JSON files...", end='')
+# cleanup_metadata_files(music_directory)
+# print("Done.")
# TODO: Implement
@@ -374,69 +384,122 @@ def handle_downloading_playlist():
# [s for s in new_filename if s.isalnum() or s == '_'])).lower()
# return new_filename
-
-if __name__ == "__main__":
+def tag_song(filename, song_data):
try:
- args = get_command_line_options()
- except Exception as ex:
- print(ex)
- sys.exit()
-
- music_directory = args.output
-
- app = create_youtube_music_api_object(args.headers)
-
- all_songs = get_library_songs(app, args)
-
- ytdl = create_downloader(music_directory)
-
- for song in all_songs:
- # download song
- ytdl.extract_info(song['url'], download=True)
-
- # get filename song was downloaded to
- filenames = glob.glob(os.path.join(music_directory, song['id'] + '.*'))
- filename = filenames[0]
-
# tag basic data
file = music_tag.load_file(filename)
- file['name'] = song['title']
- file['artist'] = song['artists'][0]
- file['albumartist'] = song['artists'][0]
- file['album'] = song['album']
- file['tracknumber'] = song['track']
- file['year'] = song['year']
+ file['name'] = song_data['title']
+ file['artist'] = song_data['artists'][0]
+ file['albumartist'] = song_data['artists'][0]
+ file['album'] = song_data['album']
+ file['tracknumber'] = song_data['track']
+ file['year'] = song_data['year']
# include album cover
try:
# NOTE: this will be at least None
- if song['thumbnail_filepath']:
- with open(song['thumbnail_filepath'], 'rb') as img_in:
+ if song_data['thumbnail_filepath']:
+ with open(song_data['thumbnail_filepath'], 'rb') as img_in:
file['artwork'] = img_in.read()
- except Exception as ex:
- print(ex)
+
+ except Exception:
+ raise UnableToFindThumbnailFileError()
# save music tag data
file.save()
+ except Exception:
+ print("could not tag song!")
+
+def move_song_to_permanent_location(music_directory, song_data, filename):
+ try:
# move song to music_directory/artist/album/artist_album_title.ext
# excluding non filesafe characters
-
artist_for_filename = remove_special_characters_for_filename(
- song['artists'][0])
+ song_data['artists'][0])
album_for_filename = remove_special_characters_for_filename(
- song['album'])
+ song_data['album'])
title_for_filename = remove_special_characters_for_filename(
- song['title'])
+ song_data['title'])
+
song_output_dir = os.path.join(music_directory,
artist_for_filename,
album_for_filename)
- Path(song_output_dir).mkdir(parents=True, exist_ok=True)
+ try:
+ Path(song_output_dir).mkdir(parents=True, exist_ok=True)
+ except OSError as ex:
+ raise UnableToCreateAlbumDirectoryError(ex)
new_filename = '{}_{}_{}.mp3'.format(artist_for_filename,
album_for_filename,
title_for_filename)
shutil.move(filename, os.path.join(song_output_dir, new_filename))
- print("done")
+ except Exception:
+ print("could not move file to correct directory!")
+
+
+def download_songs(ytdl, music_directory, songs):
+ for song in songs:
+ try:
+ # download song
+ ytdl.extract_info(song['url'], download=True)
+
+ # get filename song was downloaded to
+ filenames = glob.glob(
+ os.path.join(music_directory, song['id'] + '.*'))
+ filename = filenames[0]
+
+ if not filename:
+ raise FileNotFoundError()
+
+ tag_song(filename, song)
+
+ move_song_to_permanent_location(music_directory, song, filename)
+ except UnableToCreateAlbumDirectoryError as ex:
+ add_to_failed_songs(song, ex)
+ print('Could not download {} - {}, moving on'.format(
+ song['title'],
+ song['artists'][0]))
+ except FileNotFoundError:
+ error_reason = 'Thought song downloaded, but filename was None'
+ add_to_failed_songs(song, error_reason)
+ print('Could not download {} - {}, moving on'.format(
+ song['title'],
+ song['artists'][0]))
+
+ except Exception:
+ add_to_failed_songs(
+ song,
+ 'Unknown exception while downloading song.')
+ print('Could not download {} - {}, moving on'.format(
+ song['title'],
+ song['artists'][0]))
+
+
+def add_to_failed_songs(song, reason):
+ song['error_reason'] = reason
+ global FAILED_SONGS
+ FAILED_SONGS.append(song)
+
+
+if __name__ == "__main__":
+ try:
+ args = get_command_line_options()
+
+ music_directory = args.output
+
+ app = create_youtube_music_api_object(args.headers)
+
+ songs = get_library_songs(app, args)
+
+ ytdl = create_downloader(music_directory)
+
+ download_songs(ytdl, music_directory, songs)
+
+ except Exception as ex:
+ print(ex)
+ sys.exit()
+
+ print("Complete.")