mirror of
https://github.com/THIS-IS-NOT-A-BACKUP/zspotify.git
synced 2024-12-02 04:23:57 +01:00
Added --output argument for output templating
This commit is contained in:
parent
ad43153d4c
commit
543567079b
@ -47,12 +47,9 @@ def get_artist_albums(artist_id):
|
|||||||
def download_album(album):
|
def download_album(album):
|
||||||
""" Downloads songs from an album """
|
""" Downloads songs from an album """
|
||||||
artist, album_name = get_album_name(album)
|
artist, album_name = get_album_name(album)
|
||||||
artist_fixed = fix_filename(artist)
|
|
||||||
album_name_fixed = fix_filename(album_name)
|
|
||||||
tracks = get_album_tracks(album)
|
tracks = get_album_tracks(album)
|
||||||
for n, track in tqdm(enumerate(tracks, start=1), unit_scale=True, unit='Song', total=len(tracks)):
|
for n, track in tqdm(enumerate(tracks, start=1), unit_scale=True, unit='Song', total=len(tracks)):
|
||||||
download_track(track[ID], f'{artist_fixed}/{album_name_fixed}',
|
download_track('album', track[ID], extra_keys={'album_num': str(n).zfill(2), 'artist': artist, 'album': album}, disable_progressbar=True)
|
||||||
prefix=True, prefix_value=str(n), disable_progressbar=True)
|
|
||||||
|
|
||||||
|
|
||||||
def download_artist_albums(artist):
|
def download_artist_albums(artist):
|
||||||
|
@ -54,7 +54,7 @@ def client(args) -> None:
|
|||||||
print(
|
print(
|
||||||
'### SKIPPING: SONG DOES NOT EXIST ON SPOTIFY ANYMORE ###')
|
'### SKIPPING: SONG DOES NOT EXIST ON SPOTIFY ANYMORE ###')
|
||||||
else:
|
else:
|
||||||
download_track(song[TRACK][ID], 'Liked Songs/')
|
download_track('liked', song[TRACK][ID])
|
||||||
print('\n')
|
print('\n')
|
||||||
|
|
||||||
if args.search_spotify:
|
if args.search_spotify:
|
||||||
@ -75,7 +75,7 @@ def download_from_urls(urls: list[str]) -> bool:
|
|||||||
|
|
||||||
if track_id is not None:
|
if track_id is not None:
|
||||||
download = True
|
download = True
|
||||||
download_track(track_id)
|
download_track('single', track_id)
|
||||||
elif artist_id is not None:
|
elif artist_id is not None:
|
||||||
download = True
|
download = True
|
||||||
download_artist_albums(artist_id)
|
download_artist_albums(artist_id)
|
||||||
@ -87,8 +87,7 @@ def download_from_urls(urls: list[str]) -> bool:
|
|||||||
playlist_songs = get_playlist_songs(playlist_id)
|
playlist_songs = get_playlist_songs(playlist_id)
|
||||||
name, _ = get_playlist_info(playlist_id)
|
name, _ = get_playlist_info(playlist_id)
|
||||||
for song in playlist_songs:
|
for song in playlist_songs:
|
||||||
download_track(song[TRACK][ID],
|
download_track('playlist', song[TRACK][ID], extra_keys={'playlist': name})
|
||||||
fix_filename(name) + '/')
|
|
||||||
print('\n')
|
print('\n')
|
||||||
elif episode_id is not None:
|
elif episode_id is not None:
|
||||||
download = True
|
download = True
|
||||||
@ -273,7 +272,7 @@ def search(search_term):
|
|||||||
print_pos = dics.index(dic) + 1
|
print_pos = dics.index(dic) + 1
|
||||||
if print_pos == position:
|
if print_pos == position:
|
||||||
if dic['type'] == TRACK:
|
if dic['type'] == TRACK:
|
||||||
download_track(dic[ID])
|
download_track('single', dic[ID])
|
||||||
elif dic['type'] == ALBUM:
|
elif dic['type'] == ALBUM:
|
||||||
download_album(dic[ID])
|
download_album(dic[ID])
|
||||||
elif dic['type'] == ARTIST:
|
elif dic['type'] == ARTIST:
|
||||||
|
@ -20,6 +20,7 @@ LANGUAGE = 'LANGUAGE'
|
|||||||
BITRATE = 'BITRATE'
|
BITRATE = 'BITRATE'
|
||||||
SONG_ARCHIVE = 'SONG_ARCHIVE'
|
SONG_ARCHIVE = 'SONG_ARCHIVE'
|
||||||
CREDENTIALS_LOCATION = 'CREDENTIALS_LOCATION'
|
CREDENTIALS_LOCATION = 'CREDENTIALS_LOCATION'
|
||||||
|
OUTPUT = 'OUTPUT'
|
||||||
|
|
||||||
CONFIG_VALUES = {
|
CONFIG_VALUES = {
|
||||||
ROOT_PATH: { 'default': '../ZSpotify Music/', 'type': str, 'arg': '--root-path' },
|
ROOT_PATH: { 'default': '../ZSpotify Music/', 'type': str, 'arg': '--root-path' },
|
||||||
@ -37,8 +38,14 @@ CONFIG_VALUES = {
|
|||||||
BITRATE: { 'default': '', 'type': str, 'arg': '--bitrate' },
|
BITRATE: { 'default': '', 'type': str, 'arg': '--bitrate' },
|
||||||
SONG_ARCHIVE: { 'default': '.song_archive', 'type': str, 'arg': '--song-archive' },
|
SONG_ARCHIVE: { 'default': '.song_archive', 'type': str, 'arg': '--song-archive' },
|
||||||
CREDENTIALS_LOCATION: { 'default': 'credentials.json', 'type': str, 'arg': '--credentials-location' },
|
CREDENTIALS_LOCATION: { 'default': 'credentials.json', 'type': str, 'arg': '--credentials-location' },
|
||||||
|
OUTPUT: { 'default': '', 'type': str, 'arg': '--output' },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OUTPUT_DEFAULT_PLAYLIST = '{playlist}/{artist} - {song_name}.{ext}'
|
||||||
|
OUTPUT_DEFAULT_PLAYLIST_EXT = '{playlist}/{playlist_num} - {artist} - {song_name}.{ext}'
|
||||||
|
OUTPUT_DEFAULT_LIKED_SONGS = 'Liked Songs/{artist} - {song_name}.{ext}'
|
||||||
|
OUTPUT_DEFAULT_SINGLE = '{artist} - {song_name}.{ext}'
|
||||||
|
OUTPUT_DEFAULT_ALBUM = '{artist}/{album}/{album_num} - {artist} - {song_name}.{ext}'
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
Values = {}
|
Values = {}
|
||||||
@ -165,3 +172,20 @@ class Config:
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_credentials_location(cls) -> str:
|
def get_credentials_location(cls) -> str:
|
||||||
return cls.get(CREDENTIALS_LOCATION)
|
return cls.get(CREDENTIALS_LOCATION)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_output(cls, mode: str) -> str:
|
||||||
|
v = cls.get(OUTPUT)
|
||||||
|
if v:
|
||||||
|
return v
|
||||||
|
if mode == 'playlist':
|
||||||
|
return OUTPUT_DEFAULT_PLAYLIST
|
||||||
|
if mode == 'extplaylist':
|
||||||
|
return OUTPUT_DEFAULT_PLAYLIST_EXT
|
||||||
|
if mode == 'liked':
|
||||||
|
return OUTPUT_DEFAULT_LIKED_SONGS
|
||||||
|
if mode == 'single':
|
||||||
|
return OUTPUT_DEFAULT_SINGLE
|
||||||
|
if mode == 'album':
|
||||||
|
return OUTPUT_DEFAULT_ALBUM
|
||||||
|
raise ValueError()
|
||||||
|
@ -54,8 +54,7 @@ def download_playlist(playlist):
|
|||||||
p_bar = tqdm(playlist_songs, unit='song', total=len(playlist_songs), unit_scale=True)
|
p_bar = tqdm(playlist_songs, unit='song', total=len(playlist_songs), unit_scale=True)
|
||||||
enum = 1
|
enum = 1
|
||||||
for song in p_bar:
|
for song in p_bar:
|
||||||
download_track(song[TRACK][ID], fix_filename(playlist[NAME].strip()) + '/',
|
download_track('extplaylist', song[TRACK][ID], extra_keys={'playlist': playlist, 'playlist_num': str(enum).zfill(2)}, disable_progressbar=True)
|
||||||
prefix=True, prefix_value=str(enum) ,disable_progressbar=True)
|
|
||||||
p_bar.set_description(song[TRACK][NAME])
|
p_bar.set_description(song[TRACK][NAME])
|
||||||
enum += 1
|
enum += 1
|
||||||
|
|
||||||
|
@ -69,39 +69,45 @@ def get_song_duration(song_id: str) -> float:
|
|||||||
return duration
|
return duration
|
||||||
|
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
def download_track(track_id: str, extra_paths='', prefix=False, prefix_value='', disable_progressbar=False) -> None:
|
def download_track(mode: str, track_id: str, extra_keys={}, disable_progressbar=False) -> None:
|
||||||
""" Downloads raw song audio from Spotify """
|
""" Downloads raw song audio from Spotify """
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
output_template = ZSpotify.CONFIG.get_output(mode)
|
||||||
|
|
||||||
(artists, album_name, name, image_url, release_year, disc_number,
|
(artists, album_name, name, image_url, release_year, disc_number,
|
||||||
track_number, scraped_song_id, is_playable, duration_ms) = get_song_info(track_id)
|
track_number, scraped_song_id, is_playable, duration_ms) = get_song_info(track_id)
|
||||||
|
|
||||||
if ZSpotify.CONFIG.get_split_album_discs():
|
|
||||||
download_directory = os.path.join(os.path.dirname(
|
|
||||||
__file__), ZSpotify.CONFIG.get_root_path(), extra_paths, f'Disc {disc_number}')
|
|
||||||
else:
|
|
||||||
download_directory = os.path.join(os.path.dirname(
|
|
||||||
__file__), ZSpotify.CONFIG.get_root_path(), extra_paths)
|
|
||||||
|
|
||||||
song_name = fix_filename(artists[0]) + ' - ' + fix_filename(name)
|
song_name = fix_filename(artists[0]) + ' - ' + fix_filename(name)
|
||||||
if prefix:
|
|
||||||
song_name = f'{prefix_value.zfill(2)} - {song_name}' if prefix_value.isdigit(
|
|
||||||
) else f'{prefix_value} - {song_name}'
|
|
||||||
|
|
||||||
filename = os.path.join(
|
for k in extra_keys:
|
||||||
download_directory, f'{song_name}.{EXT_MAP.get(ZSpotify.CONFIG.get_download_format().lower())}')
|
output_template = output_template.replace("{"+k+"}", fix_filename(extra_keys[k]))
|
||||||
|
|
||||||
|
output_template = output_template.replace("{artist}", fix_filename(artists[0]))
|
||||||
|
output_template = output_template.replace("{album}", fix_filename(album_name))
|
||||||
|
output_template = output_template.replace("{song_name}", fix_filename(name))
|
||||||
|
output_template = output_template.replace("{release_year}", fix_filename(release_year))
|
||||||
|
output_template = output_template.replace("{disc_number}", fix_filename(disc_number))
|
||||||
|
output_template = output_template.replace("{track_number}", fix_filename(track_number))
|
||||||
|
output_template = output_template.replace("{id}", fix_filename(scraped_song_id))
|
||||||
|
output_template = output_template.replace("{track_id}", fix_filename(track_id))
|
||||||
|
output_template = output_template.replace("{ext}", EXT_MAP.get(ZSpotify.CONFIG.get_download_format().lower()))
|
||||||
|
|
||||||
|
filename = os.path.join(os.path.dirname(__file__), ZSpotify.CONFIG.get_root_path(), output_template)
|
||||||
|
filedir = os.path.dirname(filename)
|
||||||
|
|
||||||
check_name = os.path.isfile(filename) and os.path.getsize(filename)
|
check_name = os.path.isfile(filename) and os.path.getsize(filename)
|
||||||
check_id = scraped_song_id in get_directory_song_ids(download_directory)
|
check_id = scraped_song_id in get_directory_song_ids(filedir)
|
||||||
check_all_time = scraped_song_id in get_previously_downloaded()
|
check_all_time = scraped_song_id in get_previously_downloaded()
|
||||||
|
|
||||||
# a song with the same name is installed
|
# a song with the same name is installed
|
||||||
if not check_id and check_name:
|
if not check_id and check_name:
|
||||||
c = len([file for file in os.listdir(download_directory)
|
c = len([file for file in os.listdir(filedir) if re.search(f'^{filename}_', str(file))]) + 1
|
||||||
if re.search(f'^{song_name}_', file)]) + 1
|
|
||||||
|
|
||||||
filename = os.path.join(
|
fname = os.path.splitext(os.path.basename(filename))[0]
|
||||||
download_directory, f'{song_name}_{c}.{EXT_MAP.get(ZSpotify.CONFIG.get_download_format())}')
|
ext = os.path.splitext(os.path.basename(filename))[1]
|
||||||
|
|
||||||
|
filename = os.path.join(filedir, f'{fname}_{c}{ext}')
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -127,7 +133,7 @@ def download_track(track_id: str, extra_paths='', prefix=False, prefix_value='',
|
|||||||
track_id = TrackId.from_base62(track_id)
|
track_id = TrackId.from_base62(track_id)
|
||||||
stream = ZSpotify.get_content_stream(
|
stream = ZSpotify.get_content_stream(
|
||||||
track_id, ZSpotify.DOWNLOAD_QUALITY)
|
track_id, ZSpotify.DOWNLOAD_QUALITY)
|
||||||
create_download_directory(download_directory)
|
create_download_directory(filedir)
|
||||||
total_size = stream.input_stream.size
|
total_size = stream.input_stream.size
|
||||||
|
|
||||||
with open(filename, 'wb') as file, tqdm(
|
with open(filename, 'wb') as file, tqdm(
|
||||||
@ -155,7 +161,7 @@ def download_track(track_id: str, extra_paths='', prefix=False, prefix_value='',
|
|||||||
add_to_archive(scraped_song_id, artists[0], name)
|
add_to_archive(scraped_song_id, artists[0], name)
|
||||||
# add song id to download directory's .song_ids file
|
# add song id to download directory's .song_ids file
|
||||||
if not check_id:
|
if not check_id:
|
||||||
add_to_directory_song_ids(download_directory, scraped_song_id)
|
add_to_directory_song_ids(filedir, scraped_song_id)
|
||||||
|
|
||||||
if not ZSpotify.CONFIG.get_anti_ban_wait_time():
|
if not ZSpotify.CONFIG.get_anti_ban_wait_time():
|
||||||
time.sleep(ZSpotify.CONFIG.get_anti_ban_wait_time())
|
time.sleep(ZSpotify.CONFIG.get_anti_ban_wait_time())
|
||||||
|
@ -256,4 +256,4 @@ def fix_filename(name):
|
|||||||
>>> all('_' == fix_filename(chr(i)) for i in list(range(32)))
|
>>> all('_' == fix_filename(chr(i)) for i in list(range(32)))
|
||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
return re.sub(r'[/\\:|<>"?*\0-\x1f]|^(AUX|COM[1-9]|CON|LPT[1-9]|NUL|PRN)(?![^.])|^\s|[\s.]$', "_", name, flags=re.IGNORECASE)
|
return re.sub(r'[/\\:|<>"?*\0-\x1f]|^(AUX|COM[1-9]|CON|LPT[1-9]|NUL|PRN)(?![^.])|^\s|[\s.]$', "_", str(name), flags=re.IGNORECASE)
|
||||||
|
Loading…
Reference in New Issue
Block a user