Global config location
This commit is contained in:
parent
70da426463
commit
3d50d8f141
|
@ -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 <args>`, 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. \
|
||||
|
|
16
README.md
16
README.md
|
@ -31,7 +31,7 @@ Python packages:
|
|||
|
||||
```
|
||||
Basic command line usage:
|
||||
python zotify <track/album/playlist/episode/artist url> 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 <track/album/playlist/episode/artist url> 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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue