From 237bc569776085d30cb0f8a6a3c9056fc4c3c873 Mon Sep 17 00:00:00 2001 From: Shajal Kumar Chaudhary Date: Sat, 2 Nov 2024 17:13:43 +0530 Subject: [PATCH 1/2] Tried making changes to the download_multiple_songs() function --- spotdl/download/downloader.py | 77 ++++++++++++++++++----------------- spotdl/utils/archive.py | 23 +++++++++++ 2 files changed, 62 insertions(+), 38 deletions(-) diff --git a/spotdl/download/downloader.py b/spotdl/download/downloader.py index 86844c48e..09395bcf8 100644 --- a/spotdl/download/downloader.py +++ b/spotdl/download/downloader.py @@ -275,7 +275,6 @@ def download_multiple_songs( logger.info( "Fetching %d album%s", len(albums), "s" if len(albums) > 1 else "" ) - songs.extend(songs_from_albums(list(albums))) # Remove duplicates @@ -287,52 +286,55 @@ def download_multiple_songs( logger.debug("Downloading %d songs", len(songs)) + # Filter out already downloaded songs if self.settings["archive"]: songs = [song for song in songs if song.url not in self.url_archive] logger.debug("Filtered %d songs with archive", len(songs)) - self.progress_handler.set_song_count(len(songs)) - - # Create tasks list - tasks = [self.pool_download(song) for song in songs] - - # Call all task asynchronously, and wait until all are finished - results = list(self.loop.run_until_complete(asyncio.gather(*tasks))) + # Initialize the archive file (create it if it doesn't exist) + self.url_archive.initialize(self.settings["archive"]) - # Print errors - if self.settings["print_errors"]: - for error in self.errors: - logger.error(error) - - if self.settings["save_errors"]: - with open( - self.settings["save_errors"], "w", encoding="utf-8" - ) as error_file: - error_file.write("\n".join(self.errors)) - - logger.info("Saved errors to %s", self.settings["save_errors"]) + self.progress_handler.set_song_count(len(songs)) - # Save archive - if self.settings["archive"]: - for result in results: - if result[1] or self.settings["add_unavailable"]: - self.url_archive.add(result[0].url) + results = [] + try: + # Create tasks list + tasks = [self.pool_download(song) for song in songs] + + # Call all tasks asynchronously, and wait until all are finished + results = list(self.loop.run_until_complete(asyncio.gather(*tasks))) + + # Print errors + if self.settings["print_errors"]: + for error in self.errors: + logger.error(error) + + if self.settings["save_errors"]: + with open( + self.settings["save_errors"], "w", encoding="utf-8" + ) as error_file: + error_file.write("\n".join(self.errors)) + logger.info("Saved errors to %s", self.settings["save_errors"]) + + except Exception as e: + logger.error(f"An error occurred: {str(e)}") + + finally: + # Save archive incrementally after each successful download + if self.settings["archive"]: + for result in results: + if result[1] or self.settings["add_unavailable"]: + self.url_archive.add(result[0].url) + # Call the add_entry function to update the archive and flush + self.url_archive.add_entry(self.settings["archive"], result[0].url) - self.url_archive.save(self.settings["archive"]) - logger.info( - "Saved archive with %d urls to %s", - len(self.url_archive), - self.settings["archive"], - ) + logger.info( + "Archive saved with %d URLs", len(self.url_archive) + ) # Create m3u playlist if self.settings["m3u"]: - song_list = [ - song - for song, path in results - if path or self.settings["add_unavailable"] - ] - + song_list = [song for song, path in results if path or self.settings["add_unavailable"]] gen_m3u_files( song_list, self.settings["m3u"], @@ -347,7 +349,6 @@ def download_multiple_songs( if self.settings["save_file"]: with open(self.settings["save_file"], "w", encoding="utf-8") as save_file: json.dump([song.json for song, _ in results], save_file, indent=4) - logger.info("Saved results to %s", self.settings["save_file"]) return results diff --git a/spotdl/utils/archive.py b/spotdl/utils/archive.py index 66e79f969..8923f68d8 100644 --- a/spotdl/utils/archive.py +++ b/spotdl/utils/archive.py @@ -47,3 +47,26 @@ def save(self, file: str) -> bool: archive.write(f"{element}\n") return True + + def initialize(self, file: str) -> None: + """ + Create the archive file if it doesn't exist. + + ### Arguments + - file: the file name of the archive + """ + if not Path(file).exists(): + with open(file, "w", encoding="utf-8") as archive: + archive.write("") + + def add_entry(self, file: str, url: str) -> None: + """ + Adds an entry to the archive file and flushes it immediately. + + ### Arguments + - file: the file name of the archive + - url: the URL to append to the archive file + """ + with open(file, "a", encoding="utf-8") as archive: + archive.write(f"{url}\n") + archive.flush() \ No newline at end of file From ad080beb2c2248c917be1c302a78989568ef74ef Mon Sep 17 00:00:00 2001 From: Shajal Kumar Chaudhary Date: Sat, 2 Nov 2024 18:28:31 +0530 Subject: [PATCH 2/2] Made changes to --archive to allow saving the links to downloaded songs incrementally. Closes #2196 --- spotdl/download/downloader.py | 25 +++++++++++++++---------- spotdl/utils/archive.py | 2 +- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/spotdl/download/downloader.py b/spotdl/download/downloader.py index 09395bcf8..dd6763f82 100644 --- a/spotdl/download/downloader.py +++ b/spotdl/download/downloader.py @@ -234,6 +234,9 @@ def __init__( # Initialize archive self.url_archive = Archive() if self.settings["archive"]: + # Ensure the archive file is created if it doesn't exist + self.url_archive.initialize(self.settings["archive"]) + # Attempt to load the existing URLs from the archive self.url_archive.load(self.settings["archive"]) logger.debug("Archive: %d urls", len(self.url_archive)) @@ -291,9 +294,6 @@ def download_multiple_songs( songs = [song for song in songs if song.url not in self.url_archive] logger.debug("Filtered %d songs with archive", len(songs)) - # Initialize the archive file (create it if it doesn't exist) - self.url_archive.initialize(self.settings["archive"]) - self.progress_handler.set_song_count(len(songs)) results = [] @@ -318,23 +318,28 @@ def download_multiple_songs( except Exception as e: logger.error(f"An error occurred: {str(e)}") - + finally: # Save archive incrementally after each successful download if self.settings["archive"]: for result in results: + # Check if the download was successful if result[1] or self.settings["add_unavailable"]: + # Add the URL to the archive and write to the file self.url_archive.add(result[0].url) - # Call the add_entry function to update the archive and flush - self.url_archive.add_entry(self.settings["archive"], result[0].url) + self.url_archive.add_entry( + self.settings["archive"], result[0].url + ) - logger.info( - "Archive saved with %d URLs", len(self.url_archive) - ) + logger.info("Archive saved with %d URLs", len(self.url_archive)) # Create m3u playlist if self.settings["m3u"]: - song_list = [song for song, path in results if path or self.settings["add_unavailable"]] + song_list = [ + song + for song, path in results + if path or self.settings["add_unavailable"] + ] gen_m3u_files( song_list, self.settings["m3u"], diff --git a/spotdl/utils/archive.py b/spotdl/utils/archive.py index 8923f68d8..224144d12 100644 --- a/spotdl/utils/archive.py +++ b/spotdl/utils/archive.py @@ -69,4 +69,4 @@ def add_entry(self, file: str, url: str) -> None: """ with open(file, "a", encoding="utf-8") as archive: archive.write(f"{url}\n") - archive.flush() \ No newline at end of file + archive.flush()