Check existence before getting url

This commit is contained in:
Christoph Stahl 2025-08-10 22:51:03 +02:00
parent e1c860a711
commit 4b1e1af453

View file

@ -19,6 +19,7 @@ class Track:
title: str title: str
nr: int nr: int
id: str id: str
dest_path: str
@dataclass @dataclass
@ -53,6 +54,7 @@ class Album:
image: ImageLink image: ImageLink
release_date: datetime.date release_date: datetime.date
cover_data: bytes | None cover_data: bytes | None
dest_path: str
@classmethod @classmethod
def from_dict(cls, data: dict[Any, Any]) -> "Album": def from_dict(cls, data: dict[Any, Any]) -> "Album":
@ -63,6 +65,9 @@ class Album:
# Fetch image # Fetch image
print(f"Fetching image from {image.large}") print(f"Fetching image from {image.large}")
image_content = requests.get(image.large).content image_content = requests.get(image.large).content
album_path = f"{data['artist']['name']} - {data['title']}".replace(
"/", "-"
).replace("\\", "-")
album = cls( album = cls(
artist=data["artist"]["name"], artist=data["artist"]["name"],
@ -74,6 +79,7 @@ class Album:
image=ImageLink.from_dict(data["image"]), image=ImageLink.from_dict(data["image"]),
release_date=release_date, release_date=release_date,
cover_data=image_content, cover_data=image_content,
dest_path=album_path,
) )
if "tracks" in data and "track_ids" in data: if "tracks" in data and "track_ids" in data:
@ -83,6 +89,7 @@ class Album:
id=tid, id=tid,
title=track["title"], title=track["title"],
album=album, album=album,
dest_path=f"{album.dest_path}/{album.artist} - {album.title} - {tnr + 1} {track['title']}.flac",
) )
for tnr, (tid, track) in enumerate( for tnr, (tid, track) in enumerate(
zip(data["track_ids"], data["tracks"]["items"]) zip(data["track_ids"], data["tracks"]["items"])
@ -108,19 +115,14 @@ class Qobuz:
return result_json["data"]["url"] return result_json["data"]["url"]
raise RuntimeError(f"Failed to get download URL, result: {result}") raise RuntimeError(f"Failed to get download URL, result: {result}")
def download_track(self, track: Track, filename: str, dest: str) -> None: def download_track(self, track: Track) -> None:
download_url = self.get_download_url(track.id) download_url = self.get_download_url(track.id)
dest_path = os.path.join(dest, filename) dest_path = track.dest_path
if os.path.exists(dest_path):
skip = input(f"File {dest_path} already exists, skip download? [Y/n] ")
if skip.strip().lower() != "n":
print("Skipping download.")
return
response = requests.get(download_url, stream=True) response = requests.get(download_url, stream=True)
if response.status_code == 200: if response.status_code == 200:
total_size = int(response.headers.get("content-length", 0)) total_size = int(response.headers.get("content-length", 0))
with tqdm.tqdm( with tqdm.tqdm(
total=total_size, unit="B", unit_scale=True, desc=filename total=total_size, unit="B", unit_scale=True, desc=track.title
) as pbar: ) as pbar:
with open(dest_path, "wb") as file: with open(dest_path, "wb") as file:
for chunk in response.iter_content(chunk_size=8192): for chunk in response.iter_content(chunk_size=8192):
@ -146,7 +148,7 @@ class Qobuz:
audio.add_picture(picture) audio.add_picture(picture)
audio.save() audio.save()
print(f"Downloaded {filename}") print(f"Downloaded {dest_path} successfully.")
else: else:
raise RuntimeError("Failed to download track") raise RuntimeError("Failed to download track")
@ -158,26 +160,30 @@ class Qobuz:
return Album.from_dict(data) return Album.from_dict(data)
raise RuntimeError(f"Failed to get album, result: {result}") raise RuntimeError(f"Failed to get album, result: {result}")
def download_album(self, album: Album, dest: str) -> None: def download_album(self, album: Album) -> None:
artist = album.artist artist = album.artist
album_title = album.title album_title = album.title
tracks = album.tracks if album.tracks is not None else [] tracks = album.tracks if album.tracks is not None else []
if os.path.exists(dest): if os.path.exists(album.dest_path):
skip = input(f"Destination {dest} already exists, skip download? [Y/n] ") skip = input(
f"Destination {album.dest_path} already exists, skip download? [Y/n] "
)
if skip.strip().lower() != "n": if skip.strip().lower() != "n":
print("Skipping download.") print("Skipping download.")
return return
os.makedirs(dest, exist_ok=True) os.makedirs(album.dest_path, exist_ok=True)
print(f"Downloading album: {artist} - {album_title}") print(f"Downloading album: {artist} - {album_title}")
for nr, track in enumerate(tracks): for nr, track in enumerate(tracks):
print(f"Downloading track #{nr + 1:02d} {track.title}...") print(f"Downloading track #{nr + 1:02d} {track.title}...")
filename = ( if os.path.exists(track.dest_path):
f"{artist} - {album_title} - {nr + 1:02d} {track.title}.flac".replace( skip = input(
"/", "-" f"File {track.dest_path} already exists, skip download? [Y/n] "
).replace("\\", "-") )
) if skip.strip().lower() != "n":
self.download_track(track, filename, dest) print("Skipping download.")
return
self.download_track(track)
def search_album(self, query: str) -> Album: def search_album(self, query: str) -> Album:
print(f'Searching for "{query}"') print(f'Searching for "{query}"')
@ -190,9 +196,7 @@ class Qobuz:
def search_and_download(self, query: str) -> None: def search_and_download(self, query: str) -> None:
album = self.search_album(query) album = self.search_album(query)
safe_title = album.title.replace("/", "-").replace("\\", "-") self.download_album(album)
safe_artist = album.artist.replace("/", "-").replace("\\", "-")
self.download_album(album, f"{safe_artist} - {safe_title}")
def get_config() -> ConfigParser: def get_config() -> ConfigParser: