mirror of
https://github.com/THIS-IS-NOT-A-BACKUP/zspotify.git
synced 2024-11-26 09:53:17 +01:00
Only query genres if track does not get skipped
This commit is contained in:
parent
dc20e4367c
commit
42b7c1bd72
@ -19,8 +19,7 @@ def client(args) -> None:
|
|||||||
""" Connects to spotify to perform query's and get songs to download """
|
""" Connects to spotify to perform query's and get songs to download """
|
||||||
ZSpotify(args)
|
ZSpotify(args)
|
||||||
|
|
||||||
if ZSpotify.CONFIG.get_print_splash():
|
Printer.print(PrintChannel.SPLASH, splash())
|
||||||
Printer.print(PrintChannel.SPLASH, splash())
|
|
||||||
|
|
||||||
if ZSpotify.check_premium():
|
if ZSpotify.check_premium():
|
||||||
Printer.print(PrintChannel.SPLASH, '[ DETECTED PREMIUM ACCOUNT - USING VERY_HIGH QUALITY ]\n\n')
|
Printer.print(PrintChannel.SPLASH, '[ DETECTED PREMIUM ACCOUNT - USING VERY_HIGH QUALITY ]\n\n')
|
||||||
|
@ -70,6 +70,7 @@ OUTPUT_DEFAULT_LIKED_SONGS = 'Liked Songs/{artist} - {song_name}.{ext}'
|
|||||||
OUTPUT_DEFAULT_SINGLE = '{artist} - {song_name}.{ext}'
|
OUTPUT_DEFAULT_SINGLE = '{artist} - {song_name}.{ext}'
|
||||||
OUTPUT_DEFAULT_ALBUM = '{artist}/{album}/{album_num} - {artist} - {song_name}.{ext}'
|
OUTPUT_DEFAULT_ALBUM = '{artist}/{album}/{album_num} - {artist} - {song_name}.{ext}'
|
||||||
|
|
||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
Values = {}
|
Values = {}
|
||||||
|
|
||||||
@ -206,15 +207,11 @@ class Config:
|
|||||||
return os.path.join(cls.get_root_path(), cls.get(TEMP_DOWNLOAD_DIR))
|
return os.path.join(cls.get_root_path(), cls.get(TEMP_DOWNLOAD_DIR))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_allGenres(cls) -> bool:
|
def get_all_genres(cls) -> bool:
|
||||||
return cls.get(MD_ALLGENRES)
|
return cls.get(MD_ALLGENRES)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_print_splash(cls) -> bool:
|
def get_all_genres_delimiter(cls) -> bool:
|
||||||
return cls.get(PRINT_SPLASH)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_allGenresDelimiter(cls) -> bool:
|
|
||||||
return cls.get(MD_GENREDELIMITER)
|
return cls.get(MD_GENREDELIMITER)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -248,3 +245,7 @@ class Config:
|
|||||||
return os.path.join(split[0], 'Disc {disc_number}', split[0])
|
return os.path.join(split[0], 'Disc {disc_number}', split[0])
|
||||||
return OUTPUT_DEFAULT_ALBUM
|
return OUTPUT_DEFAULT_ALBUM
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_retry_attempts(cls) -> int:
|
||||||
|
return cls.get(RETRY_ATTEMPTS)
|
@ -34,6 +34,8 @@ ITEMS = 'items'
|
|||||||
|
|
||||||
NAME = 'name'
|
NAME = 'name'
|
||||||
|
|
||||||
|
HREF = 'href'
|
||||||
|
|
||||||
ID = 'id'
|
ID = 'id'
|
||||||
|
|
||||||
URL = 'url'
|
URL = 'url'
|
||||||
|
@ -9,7 +9,7 @@ from librespot.metadata import TrackId
|
|||||||
from ffmpy import FFmpeg
|
from ffmpy import FFmpeg
|
||||||
|
|
||||||
from const import TRACKS, ALBUM, GENRES, NAME, ITEMS, DISC_NUMBER, TRACK_NUMBER, IS_PLAYABLE, ARTISTS, IMAGES, URL, \
|
from const import TRACKS, ALBUM, GENRES, NAME, ITEMS, DISC_NUMBER, TRACK_NUMBER, IS_PLAYABLE, ARTISTS, IMAGES, URL, \
|
||||||
RELEASE_DATE, ID, TRACKS_URL, SAVED_TRACKS_URL, TRACK_STATS_URL, CODEC_MAP, EXT_MAP, DURATION_MS
|
RELEASE_DATE, ID, TRACKS_URL, SAVED_TRACKS_URL, TRACK_STATS_URL, CODEC_MAP, EXT_MAP, DURATION_MS, HREF
|
||||||
from termoutput import Printer, PrintChannel
|
from termoutput import Printer, PrintChannel
|
||||||
from utils import fix_filename, set_audio_tags, set_music_thumbnail, create_download_directory, \
|
from utils import fix_filename, set_audio_tags, set_music_thumbnail, create_download_directory, \
|
||||||
get_directory_song_ids, add_to_directory_song_ids, get_previously_downloaded, add_to_archive, fmt_seconds
|
get_directory_song_ids, add_to_directory_song_ids, get_previously_downloaded, add_to_archive, fmt_seconds
|
||||||
@ -35,7 +35,7 @@ def get_saved_tracks() -> list:
|
|||||||
return songs
|
return songs
|
||||||
|
|
||||||
|
|
||||||
def get_song_info(song_id) -> Tuple[List[str], List[str], str, str, Any, Any, Any, Any, Any, Any, int]:
|
def get_song_info(song_id) -> Tuple[List[str], List[Any], str, str, Any, Any, Any, Any, Any, Any, int]:
|
||||||
""" Retrieves metadata for downloaded songs """
|
""" Retrieves metadata for downloaded songs """
|
||||||
with Loader(PrintChannel.PROGRESS_INFO, "Fetching track information..."):
|
with Loader(PrintChannel.PROGRESS_INFO, "Fetching track information..."):
|
||||||
(raw, info) = ZSpotify.invoke_url(f'{TRACKS_URL}?ids={song_id}&market=from_token')
|
(raw, info) = ZSpotify.invoke_url(f'{TRACKS_URL}?ids={song_id}&market=from_token')
|
||||||
@ -45,21 +45,8 @@ def get_song_info(song_id) -> Tuple[List[str], List[str], str, str, Any, Any, An
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
artists = []
|
artists = []
|
||||||
genres = []
|
|
||||||
for data in info[TRACKS][0][ARTISTS]:
|
for data in info[TRACKS][0][ARTISTS]:
|
||||||
artists.append(data[NAME])
|
artists.append(data[NAME])
|
||||||
# query artist genres via href, which will be the api url
|
|
||||||
with Loader(PrintChannel.PROGRESS_INFO, "Fetching artist information..."):
|
|
||||||
(raw, artistInfo) = ZSpotify.invoke_url(f'{data["href"]}')
|
|
||||||
if ZSpotify.CONFIG.get_allGenres() and len(artistInfo[GENRES]) > 0:
|
|
||||||
for genre in artistInfo[GENRES]:
|
|
||||||
genres.append(genre)
|
|
||||||
elif len(artistInfo[GENRES]) > 0:
|
|
||||||
genres.append(artistInfo[GENRES][0])
|
|
||||||
|
|
||||||
if len(genres) == 0:
|
|
||||||
Printer.print(PrintChannel.WARNINGS, '### No Genres found for song ' + info[TRACKS][0][NAME])
|
|
||||||
genres.append('')
|
|
||||||
|
|
||||||
album_name = info[TRACKS][0][ALBUM][NAME]
|
album_name = info[TRACKS][0][ALBUM][NAME]
|
||||||
name = info[TRACKS][0][NAME]
|
name = info[TRACKS][0][NAME]
|
||||||
@ -71,11 +58,34 @@ def get_song_info(song_id) -> Tuple[List[str], List[str], str, str, Any, Any, An
|
|||||||
is_playable = info[TRACKS][0][IS_PLAYABLE]
|
is_playable = info[TRACKS][0][IS_PLAYABLE]
|
||||||
duration_ms = info[TRACKS][0][DURATION_MS]
|
duration_ms = info[TRACKS][0][DURATION_MS]
|
||||||
|
|
||||||
return artists, genres, album_name, name, image_url, release_year, disc_number, track_number, scraped_song_id, is_playable, duration_ms
|
return artists, info[TRACKS][0][ARTISTS], album_name, name, image_url, release_year, disc_number, track_number, scraped_song_id, is_playable, duration_ms
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(f'Failed to parse TRACKS_URL response: {str(e)}\n{raw}')
|
raise ValueError(f'Failed to parse TRACKS_URL response: {str(e)}\n{raw}')
|
||||||
|
|
||||||
|
|
||||||
|
def get_song_genres(rawartists: List[str], track_name: str) -> List[str]:
|
||||||
|
|
||||||
|
try:
|
||||||
|
genres = []
|
||||||
|
for data in rawartists:
|
||||||
|
# query artist genres via href, which will be the api url
|
||||||
|
with Loader(PrintChannel.PROGRESS_INFO, "Fetching artist information..."):
|
||||||
|
(raw, artistInfo) = ZSpotify.invoke_url(f'{data[HREF]}')
|
||||||
|
if ZSpotify.CONFIG.get_all_genres() and len(artistInfo[GENRES]) > 0:
|
||||||
|
for genre in artistInfo[GENRES]:
|
||||||
|
genres.append(genre)
|
||||||
|
elif len(artistInfo[GENRES]) > 0:
|
||||||
|
genres.append(artistInfo[GENRES][0])
|
||||||
|
|
||||||
|
if len(genres) == 0:
|
||||||
|
Printer.print(PrintChannel.WARNINGS, '### No Genres found for song ' + track_name)
|
||||||
|
genres.append('')
|
||||||
|
|
||||||
|
return genres
|
||||||
|
except Exception as e:
|
||||||
|
raise ValueError(f'Failed to parse GENRES response: {str(e)}\n{raw}')
|
||||||
|
|
||||||
|
|
||||||
def get_song_duration(song_id: str) -> float:
|
def get_song_duration(song_id: str) -> float:
|
||||||
""" Retrieves duration of song in second as is on spotify """
|
""" Retrieves duration of song in second as is on spotify """
|
||||||
|
|
||||||
@ -106,7 +116,7 @@ def download_track(mode: str, track_id: str, extra_keys=None, disable_progressba
|
|||||||
try:
|
try:
|
||||||
output_template = ZSpotify.CONFIG.get_output(mode)
|
output_template = ZSpotify.CONFIG.get_output(mode)
|
||||||
|
|
||||||
(artists, genres, album_name, name, image_url, release_year, disc_number,
|
(artists, raw_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)
|
||||||
|
|
||||||
song_name = fix_filename(artists[0]) + ' - ' + fix_filename(name)
|
song_name = fix_filename(artists[0]) + ' - ' + fix_filename(name)
|
||||||
@ -201,6 +211,8 @@ def download_track(mode: str, track_id: str, extra_keys=None, disable_progressba
|
|||||||
|
|
||||||
time_downloaded = time.time()
|
time_downloaded = time.time()
|
||||||
|
|
||||||
|
genres = get_song_genres(raw_artists, name)
|
||||||
|
|
||||||
convert_audio_format(filename_temp)
|
convert_audio_format(filename_temp)
|
||||||
set_audio_tags(filename_temp, artists, genres, name, album_name, release_year, disc_number, track_number)
|
set_audio_tags(filename_temp, artists, genres, name, album_name, release_year, disc_number, track_number)
|
||||||
set_music_thumbnail(filename_temp, image_url)
|
set_music_thumbnail(filename_temp, image_url)
|
||||||
|
@ -129,7 +129,7 @@ def set_audio_tags(filename, artists, genres, name, album_name, release_year, di
|
|||||||
tags = music_tag.load_file(filename)
|
tags = music_tag.load_file(filename)
|
||||||
tags[ALBUMARTIST] = artists[0]
|
tags[ALBUMARTIST] = artists[0]
|
||||||
tags[ARTIST] = conv_artist_format(artists)
|
tags[ARTIST] = conv_artist_format(artists)
|
||||||
tags[GENRE] = genres[0] if not ZSpotify.CONFIG.get_allGenres() else ZSpotify.CONFIG.get_allGenresDelimiter().join(genres)
|
tags[GENRE] = genres[0] if not ZSpotify.CONFIG.get_all_genres() else ZSpotify.CONFIG.get_all_genres_delimiter().join(genres)
|
||||||
tags[TRACKTITLE] = name
|
tags[TRACKTITLE] = name
|
||||||
tags[ALBUM] = album_name
|
tags[ALBUM] = album_name
|
||||||
tags[YEAR] = release_year
|
tags[YEAR] = release_year
|
||||||
@ -273,9 +273,9 @@ def fmt_seconds(secs: float) -> str:
|
|||||||
h = math.floor(val)
|
h = math.floor(val)
|
||||||
|
|
||||||
if h == 0 and m == 0 and s == 0:
|
if h == 0 and m == 0 and s == 0:
|
||||||
return "0"
|
return "0s"
|
||||||
elif h == 0 and m == 0:
|
elif h == 0 and m == 0:
|
||||||
return f'{s}'.zfill(2)
|
return f'{s}s'.zfill(2)
|
||||||
elif h == 0:
|
elif h == 0:
|
||||||
return f'{m}'.zfill(2) + ':' + f'{s}'.zfill(2)
|
return f'{m}'.zfill(2) + ':' + f'{s}'.zfill(2)
|
||||||
else:
|
else:
|
||||||
|
@ -82,7 +82,7 @@ class ZSpotify:
|
|||||||
responsejson = response.json()
|
responsejson = response.json()
|
||||||
|
|
||||||
if 'error' in responsejson:
|
if 'error' in responsejson:
|
||||||
if tryCount < (cls.CONFIG.retry_attemps - 1):
|
if tryCount < (cls.CONFIG.get_retry_attempts() - 1):
|
||||||
Printer.print(PrintChannel.WARNINGS, f"Spotify API Error (try {tryCount + 1}) ({responsejson['error']['status']}): {responsejson['error']['message']}")
|
Printer.print(PrintChannel.WARNINGS, f"Spotify API Error (try {tryCount + 1}) ({responsejson['error']['status']}): {responsejson['error']['message']}")
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
return cls.invoke_url(url, tryCount + 1)
|
return cls.invoke_url(url, tryCount + 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user