diff --git a/CHANGELOG.md b/CHANGELOG.md index d2b6055..2fc66d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,14 @@ ## v0.6 **General changes** - Switched from os.path to pathlib -- Zotify can now be installed with pip \ +- Zotify can now be installed with pip - `pip install https://gitlab.com/team-zotify/zotify/-/archive/main/zotify-main.zip` -- Zotify can be ran from any directory with `zotify `, you no longer need to prefix `python` in the command. +- Zotify can be ran from any directory with `zotify [args]`, you no longer need to prefix `python` in the command. +- New default config locations: + - Windows: `%AppData%\Roaming\Zotify\config.json` + - Linux: `~/.config/zotify/config.json` + - macOS: `~/Library/Application Support/Zotify/config.json` + - You can still use `--config-location` to specify a local config file. **Docker** - Dockerfile is currently broken, it will be fixed soon. \ diff --git a/README.md b/README.md index 81e8122..9f7cd95 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Python packages: ``` Basic command line usage: - python zotify Downloads the track, album, playlist or podcast episode specified as a command line argument. If an artist url is given, all albums by specified artist will be downloaded. Can take multiple urls. + zotify Downloads the track, album, playlist or podcast episode specified as a command line argument. If an artist url is given, all albums by specified artist will be downloaded. Can take multiple urls. Different usage modes: (nothing) Download the tracks/alumbs/playlists URLs from the parameter @@ -42,15 +42,15 @@ Different usage modes: Extra command line options: -ns, --no-splash Suppress the splash screen when loading. - --config-location Use a different zconfig.json, defaults to the one in the program directory + --config-location Use a different config.json. ``` ### Options: -All these options can either be configured in the zconfig or via the commandline, in case of both the commandline-option has higher priority. +All these options can either be configured in the config or via the commandline, in case of both the commandline-option has higher priority. Be aware you have to set boolean values in the commandline like this: `--download-real-time=True` -| Key (zconfig) | commandline parameter | Description +| Key (config) | commandline parameter | Description |------------------------------|----------------------------------|---------------------------------------------------------------------| | ROOT_PATH | --root-path | directory where Zotify saves the music | ROOT_PODCAST_PATH | --root-podcast-path | directory where Zotify saves the podcasts @@ -106,20 +106,20 @@ Liked Songs/{artist} - {song_name}.{ext} /home/user/downloads/{artist} - {song_name} [{id}].{ext} ~~~~ -### Docker Usage +### Docker Usage - CURRENTLY BROKEN ``` Build the docker image from the Dockerfile: docker build -t zotify . Create and run a container from the image: - docker run --rm -u $(id -u):$(id -g) -v "$PWD/zotify:/app" -v "$PWD/zconfig.json:/zconfig.json" -v "$PWD/Zotify Music:/Zotify Music" -v "$PWD/Zotify Podcasts:/Zotify Podcasts" -it zotify + docker run --rm -u $(id -u):$(id -g) -v "$PWD/zotify:/app" -v "$PWD/config.json:/config.json" -v "$PWD/Zotify Music:/Zotify Music" -v "$PWD/Zotify Podcasts:/Zotify Podcasts" -it zotify ``` ### Will my account get banned if I use this tool? Currently no user has reported their account getting banned after using Zotify. -We highly recommend using Zotify with a burner account. -Alternatively, there is a configuration option labled ```DOWNLOAD_REAL_TIME```, this limits the download speed to the duration of the song being downloaded thus not appearing suspicious. +It is recommended you use Zotify with a burner account. +Alternatively, there is a configuration option labled ```DOWNLOAD_REAL_TIME```, this limits the download speed to the duration of the song being downloaded thus appearing less suspicious. This option is much slower and is only recommended for premium users who wish to download songs in 320kbps without buying premium on a burner account. **Use Zotify at your own risk**, the developers of Zotify are not responsible if your account gets banned. diff --git a/zotify/__main__.py b/zotify/__main__.py index de8e0c8..1837bd8 100644 --- a/zotify/__main__.py +++ b/zotify/__main__.py @@ -18,7 +18,7 @@ def main(): help='Suppress the splash screen when loading.') parser.add_argument('--config-location', type=str, - help='Specify the zconfig.json location') + help='Specify the json config location') group = parser.add_mutually_exclusive_group(required=True) group.add_argument('urls', type=str, diff --git a/zotify/app.py b/zotify/app.py index 7482e43..d32f30c 100644 --- a/zotify/app.py +++ b/zotify/app.py @@ -23,10 +23,10 @@ def client(args) -> None: Printer.print(PrintChannel.SPLASH, splash()) if Zotify.check_premium(): - Printer.print(PrintChannel.SPLASH, '[ DETECTED PREMIUM ACCOUNT - USING VERY_HIGH QUALITY ]\n\n') + Printer.print(PrintChannel.WARNINGS, '[ DETECTED PREMIUM ACCOUNT - USING VERY_HIGH QUALITY ]\n\n') Zotify.DOWNLOAD_QUALITY = AudioQuality.VERY_HIGH else: - Printer.print(PrintChannel.SPLASH, '[ DETECTED FREE ACCOUNT - USING HIGH QUALITY ]\n\n') + Printer.print(PrintChannel.WARNINGS, '[ DETECTED FREE ACCOUNT - USING HIGH QUALITY ]\n\n') Zotify.DOWNLOAD_QUALITY = AudioQuality.HIGH if args.download: @@ -67,8 +67,7 @@ def download_from_urls(urls: list[str]) -> bool: download = False for spotify_url in urls: - track_id, album_id, playlist_id, episode_id, show_id, artist_id = regex_input_for_urls( - spotify_url) + track_id, album_id, playlist_id, episode_id, show_id, artist_id = regex_input_for_urls(spotify_url) if track_id is not None: download = True diff --git a/zotify/config.py b/zotify/config.py index fe290ee..c51f700 100644 --- a/zotify/config.py +++ b/zotify/config.py @@ -1,9 +1,8 @@ import json -# import os +import sys from pathlib import Path, PurePath from typing import Any -CONFIG_FILE_PATH = './zconfig.json' ROOT_PATH = 'ROOT_PATH' ROOT_PODCAST_PATH = 'ROOT_PODCAST_PATH' @@ -77,28 +76,28 @@ class Config: @classmethod def load(cls, args) -> None: - #app_dir = PurePath(__file__).parent - app_dir = Path.cwd() - - config_fp = CONFIG_FILE_PATH + system_paths = { + 'win32': Path.home() / 'AppData/Roaming/Zotify', + 'linux': Path.home() / '.config/zotify', + 'darwin': Path.home() / 'Library/Application Support/Zotify' + } + config_fp = system_paths[sys.platform] / 'config.json' if args.config_location: config_fp = args.config_location - true_config_file_path = PurePath(app_dir).joinpath(config_fp) + true_config_file_path = Path(config_fp).expanduser() # Load config from zconfig.json - + Path(PurePath(true_config_file_path).parent).mkdir(parents=True, exist_ok=True) if not Path(true_config_file_path).exists(): with open(true_config_file_path, 'w', encoding='utf-8') as config_file: json.dump(cls.get_default_json(), config_file, indent=4) - cls.Values = cls.get_default_json() - else: - with open(true_config_file_path, encoding='utf-8') as config_file: - jsonvalues = json.load(config_file) - cls.Values = {} - for key in CONFIG_VALUES: - if key in jsonvalues: - cls.Values[key] = cls.parse_arg_value(key, jsonvalues[key]) + with open(true_config_file_path, encoding='utf-8') as config_file: + jsonvalues = json.load(config_file) + cls.Values = {} + for key in CONFIG_VALUES: + if key in jsonvalues: + cls.Values[key] = cls.parse_arg_value(key, jsonvalues[key]) # Add default values for missing keys @@ -144,11 +143,13 @@ class Config: @classmethod def get_root_path(cls) -> str: - return PurePath(Path.cwd()).joinpath(cls.get(ROOT_PATH)) + # return PurePath(Path.cwd()).joinpath(cls.get(ROOT_PATH)) + return PurePath(Path(cls.get(ROOT_PATH)).expanduser()) @classmethod def get_root_podcast_path(cls) -> str: - return PurePath(Path.cwd()).joinpath(cls.get(ROOT_PODCAST_PATH)) + # return PurePath(Path.cwd()).joinpath(cls.get(ROOT_PODCAST_PATH)) + return PurePath(Path(cls.get(ROOT_PODCAST_PATH)).expanduser()) @classmethod def get_skip_existing_files(cls) -> bool: @@ -223,36 +224,26 @@ class Config: return v if mode == 'playlist': if cls.get_split_album_discs(): - # split = os.path.split(OUTPUT_DEFAULT_PLAYLIST) - # return os.path.join(split[0], 'Disc {disc_number}', split[0]) split = PurePath(OUTPUT_DEFAULT_PLAYLIST).parent return PurePath(split).joinpath('Disc {disc_number}').joinpath(split) return OUTPUT_DEFAULT_PLAYLIST if mode == 'extplaylist': if cls.get_split_album_discs(): - # split = os.path.split(OUTPUT_DEFAULT_PLAYLIST_EXT) - # return os.path.join(split[0], 'Disc {disc_number}', split[0]) split = PurePath(OUTPUT_DEFAULT_PLAYLIST_EXT).parent return PurePath(split).joinpath('Disc {disc_number}').joinpath(split) return OUTPUT_DEFAULT_PLAYLIST_EXT if mode == 'liked': if cls.get_split_album_discs(): - # split = os.path.split(OUTPUT_DEFAULT_LIKED_SONGS) - # return os.path.join(split[0], 'Disc {disc_number}', split[0]) split = PurePath(OUTPUT_DEFAULT_LIKED_SONGS).parent return PurePath(split).joinpath('Disc {disc_number}').joinpath(split) return OUTPUT_DEFAULT_LIKED_SONGS if mode == 'single': if cls.get_split_album_discs(): - # split = os.path.split(OUTPUT_DEFAULT_SINGLE) - # return os.path.join(split[0], 'Disc {disc_number}', split[0]) split = PurePath(OUTPUT_DEFAULT_SINGLE).parent return PurePath(split).joinpath('Disc {disc_number}').joinpath(split) return OUTPUT_DEFAULT_SINGLE if mode == 'album': if cls.get_split_album_discs(): - # split = os.path.split(OUTPUT_DEFAULT_ALBUM) - # return os.path.join(split[0], 'Disc {disc_number}', split[0]) split = PurePath(OUTPUT_DEFAULT_ALBUM).parent return PurePath(split).joinpath('Disc {disc_number}').joinpath(split) return OUTPUT_DEFAULT_ALBUM diff --git a/zotify/podcast.py b/zotify/podcast.py index 39e778c..63863cf 100644 --- a/zotify/podcast.py +++ b/zotify/podcast.py @@ -7,7 +7,7 @@ from librespot.metadata import EpisodeId from zotify.const import ERROR, ID, ITEMS, NAME, SHOW, DURATION_MS from zotify.termoutput import PrintChannel, Printer -from zotify.utils import create_download_directory, fix_filename +from zotify.utils import create_download_directory, fix_filename, convert_audio_format from zotify.zotify import Zotify from zotify.loader import Loader diff --git a/zotify/utils.py b/zotify/utils.py index 359e500..0d051d6 100644 --- a/zotify/utils.py +++ b/zotify/utils.py @@ -23,7 +23,6 @@ class MusicFormat(str, Enum): def create_download_directory(download_path: str) -> None: """ Create directory and add a hidden file with song ids """ - # os.makedirs(download_path, exist_ok=True) Path(download_path).mkdir(parents=True, exist_ok=True) # add hidden file with song ids @@ -282,5 +281,3 @@ def fmt_seconds(secs: float) -> str: return f'{m}'.zfill(2) + ':' + f'{s}'.zfill(2) else: return f'{h}'.zfill(2) + ':' + f'{m}'.zfill(2) + ':' + f'{s}'.zfill(2) - -