From 19fdd85c35789ba1784f6a002160beba5a9c9f6d Mon Sep 17 00:00:00 2001 From: Rafael Moraes <50295204+glomatico@users.noreply.github.com> Date: Sat, 3 Aug 2024 00:11:11 -0300 Subject: [PATCH] add `save_playlist_file` option --- gamdl/cli.py | 18 +++++++++++++++ gamdl/downloader.py | 55 ++++++++++++++++++++++++++++++++------------- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/gamdl/cli.py b/gamdl/cli.py index f7d2348..cfcb787 100644 --- a/gamdl/cli.py +++ b/gamdl/cli.py @@ -97,6 +97,11 @@ def load_config_file( is_flag=True, help="Interpret URLs as paths to text files containing URLs separated by newlines", ) +@click.option( + "--save-playlist-file", + is_flag=True, + help="Save a M3U8 playlist file when downloading a playlist.", +) @click.option( "--synced-lyrics-only", is_flag=True, @@ -237,6 +242,12 @@ def load_config_file( default=downloader_sig.parameters["template_file_no_album"].default, help="Template file for the tracks that are not part of an album.", ) +@click.option( + "--template-file-playlist", + type=str, + default=downloader_sig.parameters["template_file_playlist"].default, + help="Template file for the M3U8 playlist.", +) @click.option( "--template-date", type=str, @@ -302,6 +313,7 @@ def main( save_cover: bool, overwrite: bool, read_urls_as_txt: bool, + save_playlist_file: bool, synced_lyrics_only: bool, no_synced_lyrics: bool, config_path: Path, @@ -325,6 +337,7 @@ def main( template_file_multi_disc: str, template_folder_no_album: str, template_file_no_album: str, + template_file_playlist: str, template_date: str, exclude_tags: str, cover_size: int, @@ -372,6 +385,7 @@ def main( template_file_multi_disc, template_folder_no_album, template_file_no_album, + template_file_playlist, template_date, exclude_tags, cover_size, @@ -731,6 +745,10 @@ def main( downloader.apply_tags(remuxed_path, tags, cover_url) logger.debug(f'Moving to "{final_path}"') downloader.move_to_output_path(remuxed_path, final_path) + if save_playlist_file and download_queue.playlist_attributes: + playlist_file_path = downloader.get_playlist_file_path(tags) + logger.debug("Saving M3U8 playlist") + downloader.update_playlist_file(playlist_file_path, final_path) except Exception as e: error_count += 1 logger.error( diff --git a/gamdl/downloader.py b/gamdl/downloader.py index ff3d35e..76c1f20 100644 --- a/gamdl/downloader.py +++ b/gamdl/downloader.py @@ -50,6 +50,7 @@ class Downloader: template_file_multi_disc: str = "{disc}-{track:02d} {title}", template_folder_no_album: str = "{artist}/Unknown Album", template_file_no_album: str = "{title}", + template_file_playlist: str = "{playlist_title}", template_date: str = "%Y-%m-%dT%H:%M:%SZ", exclude_tags: str = None, cover_size: int = 1200, @@ -74,6 +75,7 @@ class Downloader: self.template_file_multi_disc = template_file_multi_disc self.template_folder_no_album = template_folder_no_album self.template_file_no_album = template_file_no_album + self.template_file_playlist = template_file_playlist self.template_date = template_date self.exclude_tags = exclude_tags self.cover_size = cover_size @@ -259,6 +261,29 @@ class Downloader: } return tags + def get_playlist_file_path( + self, + tags: dict, + ): + template_folder = self.template_file_playlist.split("/")[0:-1] + template_file = self.template_file_playlist.split("/")[-1] + return self.output_path.joinpath( + *[ + self.get_sanitized_string(i.format(**tags), True) + for i in template_folder + ] + ).joinpath( + *[self.get_sanitized_string(template_file.format(**tags), False) + ".m3u8"] + ) + + def update_playlist_file( + self, + playlist_file_path: Path, + final_path: Path, + ): + with playlist_file_path.open("a") as playlist_file: + playlist_file.write(final_path.relative_to(self.output_path).as_posix() + "\n") + @staticmethod def millis_to_min_sec(millis): minutes, seconds = divmod(millis // 1000, 60) @@ -344,30 +369,28 @@ class Downloader: def get_final_path(self, tags: dict, file_extension: str) -> Path: if tags.get("album"): - final_path_folder = ( + template_folder = ( self.template_folder_compilation.split("/") if tags.get("compilation") else self.template_folder_album.split("/") - ) - final_path_file = ( + )[0:-1] + template_file = ( self.template_file_multi_disc.split("/") if tags["disc_total"] > 1 else self.template_file_single_disc.split("/") - ) + )[-1] else: - final_path_folder = self.template_folder_no_album.split("/") - final_path_file = self.template_file_no_album.split("/") - final_path_folder = [ - self.get_sanitized_string(i.format(**tags), True) for i in final_path_folder - ] - final_path_file = [ - self.get_sanitized_string(i.format(**tags), True) - for i in final_path_file[:-1] - ] + [ - self.get_sanitized_string(final_path_file[-1].format(**tags), False) + template_folder = self.template_folder_no_album.split("/")[0:-1] + template_file = self.template_file_no_album.split("/")[-1] + return self.output_path.joinpath( + *[ + self.get_sanitized_string(i.format(**tags), True) + for i in template_folder + ] + ).joinpath( + self.get_sanitized_string(template_file.format(**tags), False) + file_extension - ] - return self.output_path.joinpath(*final_path_folder).joinpath(*final_path_file) + ) def get_cover_file_extension(self, cover_url: str) -> str: image_obj = Image.open(io.BytesIO(self.get_url_response_bytes(cover_url)))