mirror of
https://github.com/nathom/streamrip.git
synced 2025-05-09 14:11:55 -04:00
258 lines
8.3 KiB
Python
258 lines
8.3 KiB
Python
"""A config class that manages arguments between the config file and CLI."""
|
|
|
|
import logging
|
|
import os
|
|
from dataclasses import dataclass
|
|
|
|
import tomlkit
|
|
|
|
logger = logging.getLogger("streamrip")
|
|
|
|
CURRENT_CONFIG_VERSION = "2.0"
|
|
|
|
DEFAULT_CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.toml")
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class QobuzConfig:
|
|
use_auth_token: bool
|
|
email_or_userid: str
|
|
# This is an md5 hash of the plaintext password
|
|
password_or_token: str
|
|
# Do not change
|
|
app_id: str
|
|
quality: int
|
|
# This will download booklet pdfs that are included with some albums
|
|
download_booklets: bool
|
|
# Do not change
|
|
secrets: list[str]
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class TidalConfig:
|
|
# Do not change any of the fields below
|
|
user_id: str
|
|
country_code: str
|
|
access_token: str
|
|
refresh_token: str
|
|
# Tokens last 1 week after refresh. This is the Unix timestamp of the expiration
|
|
# time. If you haven't used streamrip in more than a week, you may have to log
|
|
# in again using `rip config --tidal`
|
|
token_expiry: str
|
|
# 0: 256kbps AAC, 1: 320kbps AAC, 2: 16/44.1 "HiFi" FLAC, 3: 24/44.1 "MQA" FLAC
|
|
quality: int
|
|
# This will download videos included in Video Albums.
|
|
download_videos: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class DeezerConfig:
|
|
# An authentication cookie that allows streamrip to use your Deezer account
|
|
# See https://github.com/nathom/streamrip/wiki/Finding-Your-Deezer-ARL-Cookie
|
|
# for instructions on how to find this
|
|
arl: str
|
|
# 0, 1, or 2
|
|
# This only applies to paid Deezer subscriptions. Those using deezloader
|
|
# are automatically limited to quality = 1
|
|
quality: int
|
|
# This allows for free 320kbps MP3 downloads from Deezer
|
|
# If an arl is provided, deezloader is never used
|
|
use_deezloader: bool
|
|
# This warns you when the paid deezer account is not logged in and rip falls
|
|
# back to deezloader, which is unreliable
|
|
deezloader_warnings: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class SoundcloudConfig:
|
|
# This changes periodically, so it needs to be updated
|
|
client_id: str
|
|
app_version: str
|
|
# Only 0 is available for now
|
|
quality: int
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class YoutubeConfig:
|
|
# The path to download the videos to
|
|
video_downloads_folder: str
|
|
# Only 0 is available for now
|
|
quality: int
|
|
# Download the video along with the audio
|
|
download_videos: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class DatabaseConfig:
|
|
downloads_enabled: bool
|
|
downloads_path: str
|
|
failed_downloads_enabled: bool
|
|
failed_downloads_path: str
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class ConversionConfig:
|
|
enabled: bool
|
|
# FLAC, ALAC, OPUS, MP3, VORBIS, or AAC
|
|
codec: str
|
|
# In Hz. Tracks are downsampled if their sampling rate is greater than this.
|
|
# Value of 48000 is recommended to maximize quality and minimize space
|
|
sampling_rate: int
|
|
# Only 16 and 24 are available. It is only applied when the bit depth is higher
|
|
# than this value.
|
|
bit_depth: int
|
|
# Only applicable for lossy codecs
|
|
lossy_bitrate: int
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class QobuzDiscographyFilterConfig:
|
|
# Remove Collectors Editions, live recordings, etc.
|
|
extras: bool
|
|
# Picks the highest quality out of albums with identical titles.
|
|
repeats: bool
|
|
# Remove EPs and Singles
|
|
non_albums: bool
|
|
# Remove albums whose artist is not the one requested
|
|
features: bool
|
|
# Skip non studio albums
|
|
non_studio_albums: bool
|
|
# Only download remastered albums
|
|
non_remaster: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class ArtworkConfig:
|
|
# Write the image to the audio file
|
|
embed: bool
|
|
# The size of the artwork to embed. Options: thumbnail, small, large, original.
|
|
# "original" images can be up to 30MB, and may fail embedding.
|
|
# Using "large" is recommended.
|
|
size: str
|
|
# Both of these options limit the size of the embedded artwork. If their values
|
|
# are larger than the actual dimensions of the image, they will be ignored.
|
|
# If either value is -1, the image is left untouched.
|
|
max_width: int
|
|
max_height: int
|
|
# Save the cover image at the highest quality as a seperate jpg file
|
|
keep_hires_cover: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class MetadataConfig:
|
|
# Sets the value of the 'ALBUM' field in the metadata to the playlist's name.
|
|
# This is useful if your music library software organizes tracks based on album name.
|
|
set_playlist_to_album: bool
|
|
# Replaces the original track's tracknumber with it's position in the playlist
|
|
new_playlist_tracknumbers: bool
|
|
# The following metadata tags won't be applied
|
|
# See https://github.com/nathom/streamrip/wiki/Metadata-Tag-Names for more info
|
|
exclude: list[str]
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class FilepathsConfig:
|
|
# Create folders for single tracks within the downloads directory using the folder_format
|
|
# template
|
|
add_singles_to_folder: bool
|
|
# Available keys: "albumartist", "title", "year", "bit_depth", "sampling_rate",
|
|
# "container", "id", and "albumcomposer"
|
|
folder_format: str
|
|
# Available keys: "tracknumber", "artist", "albumartist", "composer", "title",
|
|
# and "albumcomposer"
|
|
track_format: str
|
|
# Only allow printable ASCII characters in filenames.
|
|
restrict_characters: bool
|
|
# Truncate the filename if it is greater than 120 characters
|
|
# Setting this to false may cause downloads to fail on some systems
|
|
truncate: bool
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class DownloadsConfig:
|
|
# Folder where tracks are downloaded to
|
|
folder: str
|
|
# Put Qobuz albums in a 'Qobuz' folder, Tidal albums in 'Tidal' etc.
|
|
source_subdirectories: bool
|
|
# Download (and convert) tracks all at once, instead of sequentially.
|
|
# If you are converting the tracks, or have fast internet, this will
|
|
# substantially improve processing speed.
|
|
concurrency: bool
|
|
# The maximum number of tracks to download at once
|
|
# If you have very fast internet, you will benefit from a higher value,
|
|
# A value that is too high for your bandwidth may cause slowdowns
|
|
max_connections: int
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class LastFmConfig:
|
|
# The source on which to search for the tracks.
|
|
source: str
|
|
# If no results were found with the primary source, the item is searched for
|
|
# on this one.
|
|
fallback_source: str
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class ThemeConfig:
|
|
# Options: "dainty" or "plain"
|
|
progress_bar: str
|
|
|
|
|
|
@dataclass(slots=True)
|
|
class Config:
|
|
downloads: DownloadsConfig
|
|
|
|
qobuz: QobuzConfig
|
|
tidal: TidalConfig
|
|
soundcloud: SoundcloudConfig
|
|
youtube: YoutubeConfig
|
|
lastfm: LastFmConfig
|
|
|
|
filepaths: FilepathsConfig
|
|
artwork: ArtworkConfig
|
|
metadata: MetadataConfig
|
|
qobuz_filter: QobuzDiscographyFilterConfig
|
|
|
|
theme: ThemeConfig
|
|
database: DatabaseConfig
|
|
|
|
@classmethod
|
|
def from_toml(cls, toml_str: str):
|
|
# TODO: handle the mistake where Windows people forget to escape backslash
|
|
toml = tomlkit.parse(toml_str) # type: ignore
|
|
if toml["misc"]["version"] != CURRENT_CONFIG_VERSION: # type: ignore
|
|
raise Exception("Need to update config")
|
|
|
|
downloads = DownloadsConfig(**toml["downloads"]) # type: ignore
|
|
qobuz = QobuzConfig(**toml["qobuz"]) # type: ignore
|
|
tidal = TidalConfig(**toml["tidal"]) # type: ignore
|
|
soundcloud = SoundcloudConfig(**toml["soundcloud"]) # type: ignore
|
|
youtube = YoutubeConfig(**toml["youtube"]) # type: ignore
|
|
lastfm = LastFmConfig(**toml["lastfm"]) # type: ignore
|
|
artwork = ArtworkConfig(**toml["artwork"]) # type: ignore
|
|
filepaths = FilepathsConfig(**toml["filepaths"]) # type: ignore
|
|
metadata = MetadataConfig(**toml["metadata"]) # type: ignore
|
|
qobuz_filter = QobuzDiscographyFilterConfig(**toml["qobuz_filters"]) # type: ignore
|
|
theme = ThemeConfig(**toml["theme"]) # type: ignore
|
|
database = DatabaseConfig(**toml["database"]) # type: ignore
|
|
|
|
return cls(
|
|
downloads=downloads,
|
|
qobuz=qobuz,
|
|
tidal=tidal,
|
|
soundcloud=soundcloud,
|
|
youtube=youtube,
|
|
lastfm=lastfm,
|
|
artwork=artwork,
|
|
filepaths=filepaths,
|
|
metadata=metadata,
|
|
qobuz_filter=qobuz_filter,
|
|
theme=theme,
|
|
database=database,
|
|
)
|
|
|
|
@classmethod
|
|
def from_defaults(cls):
|
|
with open(DEFAULT_CONFIG_PATH) as f:
|
|
return cls.from_toml(f.read())
|