From 007727c12723abe0d8571e5ef88afd3ea0bc5a26 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Fri, 28 Oct 2022 11:03:47 +0200 Subject: [PATCH] added new functionality --- config.json | 34 ++++++++++++++++ excluded_playlists.txt | 0 playlist_downloader.py | 88 +++++++++++++++++++++++++++++++----------- spotdl_connector.py | 19 +++++---- 4 files changed, 110 insertions(+), 31 deletions(-) create mode 100644 config.json create mode 100644 excluded_playlists.txt diff --git a/config.json b/config.json new file mode 100644 index 0000000..72f01b9 --- /dev/null +++ b/config.json @@ -0,0 +1,34 @@ +{ + "default_file_type": "flac", + "output_root_folder": "/home/alex/cloud/music/playlists", + "users": [], + "excluded_playlists": [ + "https://open.spotify.com/playlist/3Kt8SPM8B6fnLGcwYRTXdK", + "https://open.spotify.com/playlist/1IxzOPHgqYhOXahfeE7J0W" + ], + "additional_playlists": [ + "https://open.spotify.com/playlist/3AGs5YAEQWtkF2XK7DMavW", + "https://open.spotify.com/playlist/6xE402f7rtWI26SDm6m2tY", + "https://open.spotify.com/playlist/36O6MRgXdxZwxAJjyGWrSv", + "https://open.spotify.com/playlist/7HxFkCjllB3CBBlee2hm8G", + "https://open.spotify.com/playlist/1j1BnjZ1zrAbQDQtCsy69Z", + "https://open.spotify.com/playlist/2fCVnp1hyjeR0rbUNtmlu2", + "https://open.spotify.com/playlist/2sgUUpzIA9r3zpZIeIBGQQ", + "https://open.spotify.com/playlist/2B5aB9zFKxnpn5mzijweNH", + "https://open.spotify.com/playlist/4C6b1gDdr3mXtuT0xzMEen", + "https://open.spotify.com/playlist/4jECXouCtgLItuxK8lDmO3", + "https://open.spotify.com/playlist/0Q42BPJTZRUFCQyw8wrk4a" + ], + "playlist_options": { + "https://open.spotify.com/playlist/3AGs5YAEQWtkF2XK7DMavW": { + "file_type": "flac" + }, + "https://open.spotify.com/playlist/6xE402f7rtWI26SDm6m2tY": { + "file_type": "flac" + }, + "https://open.spotify.com/playlist/36O6MRgXdxZwxAJjyGWrSv": { + "file_type": "flac" + } + } + +} \ No newline at end of file diff --git a/excluded_playlists.txt b/excluded_playlists.txt new file mode 100644 index 0000000..e69de29 diff --git a/playlist_downloader.py b/playlist_downloader.py index 6725d7b..91f8216 100644 --- a/playlist_downloader.py +++ b/playlist_downloader.py @@ -1,42 +1,84 @@ import sys import os +import json from spotdl_connector import download_playlist from spotify_connection import get_playlists_by_user, get_playlist_info -ADDITIONAL_PLAYLIST_FILE = "additional_playlists.txt" +CONFIG_FILE_PATH = "config.json" def main() -> None: - # check for parameters - if len(sys.argv) < 3: - print("Usage: python playlists_downloader.py [file_type]") - sys.exit(1) - username = sys.argv[1] - playlist_root = sys.argv[2] - - if len(sys.argv) < 4: - file_type = sys.argv[3] + if os.path.isfile(CONFIG_FILE_PATH): + with open(CONFIG_FILE_PATH, "r") as config_file: + config = json.load(config_file) else: - file_type = "mp3" + print("No config file (config.json) found. Exiting") + sys.exit(1) + + # get default file type from config, set to mp3, if not given + if "default_file_type" in config: + default_file_type = config["default_file_type"] + else: + default_file_type = "mp3" + + # get root output folder from config + if "output_root_folder" in config: + output_root_folder = config["output_root_folder"] + else: + print("No output root folder specified in config. Exiting") + sys.exit(1) + + # get users from which to fetch all public playlists + if "users" in config: + users = config["users"] + else: + users = list() # check for additional playlists - if os.path.isfile(ADDITIONAL_PLAYLIST_FILE): - with open(ADDITIONAL_PLAYLIST_FILE, "r") as pl_file: - additional_playlists_raw = pl_file.readlines() - - additional_playlists = [get_playlist_info(pl_uri) for pl_uri in additional_playlists_raw] - + if "additional_playlists" in config: + additional_playlists = config["additional_playlists"] else: additional_playlists = list() - user_playlists = get_playlists_by_user(username) - playlists = user_playlists + additional_playlists + # check for excluded playlists + if "excluded_playlists" in config: + excluded_playlists = config["excluded_playlists"] + else: + excluded_playlists = list() - print(f"Downloading {len(user_playlists)} public playlist(s) by {username}") - print(f"Downloading {len(additional_playlists)} additional playlist(s)") - print(f"Root for playlist folders: {playlist_root}") - [download_playlist(pl, playlist_root, file_type) for pl in playlists] + # check for specified playlist options + if "playlist_options" in config: + playlist_options = config["playlist_options"] + else: + playlist_options = dict() + + def get_playlist_meta(usernames: list, additional_playlists: list, excluded_playlists: list) -> list: + # fetches the metadata for all the playlists to download + user_playlists = [playlist for user in users for playlist in get_playlists_by_user(user)] + additional_playlists = [get_playlist_info(add_playlist) for add_playlist in additional_playlists] + all_playlists = [pl for pl in user_playlists + additional_playlists + if pl["external_urls"]["spotify"] not in excluded_playlists] + return all_playlists + + playlist_meta = get_playlist_meta(users, additional_playlists, excluded_playlists) + + # create playlist dicts with options, use default values if no specific options are given + default_playlist_options = { + "file_type": default_file_type, + "output_root_folder": output_root_folder + } + + def get_playlist_with_options(playlist_meta: dict, playlist_options: dict, default_playlist_options: dict) -> dict: + url = playlist_meta["external_urls"]["spotify"] + # combine additional values with playlist meta + return playlist_meta | default_playlist_options | (playlist_options[url] if url in playlist_options else {}) + + playlist_dicts = [get_playlist_with_options(pl, playlist_options, default_playlist_options) for pl in playlist_meta] + + print(f"Downloading {len(playlist_dicts)} playlist(s)") + print(f"Root for playlist folders: {output_root_folder}") + [download_playlist(pl) for pl in playlist_dicts] print("Done.") diff --git a/spotdl_connector.py b/spotdl_connector.py index 7a63403..f15bf33 100644 --- a/spotdl_connector.py +++ b/spotdl_connector.py @@ -1,25 +1,28 @@ import os -def download_playlist(playlist: dict, playlist_root: str, file_type: str) -> None: - print(f"Downloading playlist {playlist['name']}") +def download_playlist(playlist: dict) -> None: + playlist_name = playlist["name"] + output_root_folder = playlist["output_root_folder"] + + print(f"Downloading playlist {playlist_name}") # create playlist root, if not done yet try: - os.mkdir(playlist_root) + os.mkdir(output_root_folder) except FileExistsError: pass - os.chdir(playlist_root) + os.chdir(output_root_folder) # create playlist folder if not don yet - playlist_dir = os.path.join(playlist_root, playlist["name"]) + playlist_dir = os.path.join(output_root_folder, playlist_name) try: os.mkdir(playlist_dir) - print(f"Playlist folder for {playlist['name']} created") + print(f"Playlist folder for {playlist_name} created") except FileExistsError: - print(f"Playlist folder for {playlist['name']} already created") + print(f"Playlist folder for {playlist_name} already created") os.chdir(playlist_dir) - command = f"spotdl {playlist['external_urls']['spotify']} --output-format {file_type}" + command = f"spotdl {playlist['external_urls']['spotify']} --output-format {playlist['file_type']}" os.system(command)