diff --git a/zspotify/podcast.py b/zspotify/podcast.py index f7c337dc..686ea4ab 100644 --- a/zspotify/podcast.py +++ b/zspotify/podcast.py @@ -27,8 +27,7 @@ def get_show_episodes(show_id_str) -> list: limit = 50 while True: - resp = ZSpotify.invoke_url_with_params( - f'{SHOWS_URL}/{show_id_str}/episodes', limit=limit, offset=offset) + resp = ZSpotify.invoke_url_with_params(f'{SHOWS_URL}/{show_id_str}/episodes', limit=limit, offset=offset) offset += limit for episode in resp[ITEMS]: episodes.append(episode[ID]) @@ -38,33 +37,6 @@ def get_show_episodes(show_id_str) -> list: return episodes -def download_podcast_experimental(url, filename): - import functools - import pathlib - import shutil - import requests - from tqdm.auto import tqdm - - r = requests.get(url, stream=True, allow_redirects=True) - if r.status_code != 200: - r.raise_for_status() # Will only raise for 4xx codes, so... - raise RuntimeError( - f"Request to {url} returned status code {r.status_code}") - file_size = int(r.headers.get('Content-Length', 0)) - - path = pathlib.Path(filename).expanduser().resolve() - path.parent.mkdir(parents=True, exist_ok=True) - - desc = "(Unknown total file size)" if file_size == 0 else "" - r.raw.read = functools.partial( - r.raw.read, decode_content=True) # Decompress if needed - with tqdm.wrapattr(r.raw, "read", total=file_size, desc=desc) as r_raw: - with path.open("wb") as f: - shutil.copyfileobj(r_raw, f) - - return path - - def download_episode(episode_id) -> None: podcast_name, episode_name = get_episode_info(episode_id) @@ -75,6 +47,9 @@ def download_episode(episode_id) -> None: else: filename = podcast_name + ' - ' + episode_name + episode_id = EpisodeId.from_base62(episode_id) + stream = ZSpotify.get_content_stream(episode_id, ZSpotify.DOWNLOAD_QUALITY) + download_directory = os.path.join( os.path.dirname(__file__), ZSpotify.get_config(ROOT_PODCAST_PATH), @@ -83,12 +58,33 @@ def download_episode(episode_id) -> None: download_directory = os.path.realpath(download_directory) create_download_directory(download_directory) - filepath = os.path.join(download_directory, f"{filename}.mp3") + total_size = stream.input_stream.size - download_url = ZSpotify.invoke_url( - 'https://api-partner.spotify.com/pathfinder/v1/query?operationName=getEpisode&variables={"uri":"spotify:episode:3u0krXMhLcdGZUZkDVmMSt"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"224ba0fd89fcfdfb3a15fa2d82a6112d3f4e2ac88fba5c6713de04d1b72cf482"}}')["data"]["episode"]["audio"]["items"][-1]["url"] + filepath = os.path.join(download_directory, f"{filename}.ogg") + if ( + os.path.isfile(filepath) + and os.path.getsize(filepath) == total_size + and ZSpotify.get_config(SKIP_EXISTING_FILES) + ): + print( + "\n### SKIPPING:", + podcast_name, + "-", + episode_name, + "(EPISODE ALREADY EXISTS) ###", + ) + return - download_podcast_experimental(download_url, filepath) + with open(filepath, 'wb') as file, tqdm( + desc=filename, + total=total_size, + unit='B', + unit_scale=True, + unit_divisor=1024 + ) as bar: + for _ in range(int(total_size / ZSpotify.get_config(CHUNK_SIZE)) + 1): + bar.update(file.write( + stream.input_stream.stream().read(ZSpotify.get_config(CHUNK_SIZE)))) # convert_audio_format(ROOT_PODCAST_PATH + # extra_paths + filename + '.ogg')