mirror of
https://github.com/nathom/streamrip.git
synced 2025-05-18 17:25:22 -04:00
Cleanup
This commit is contained in:
parent
adb4b2abb5
commit
41223c1237
25 changed files with 15 additions and 1895 deletions
154
music_dl/utils.py
Normal file
154
music_dl/utils.py
Normal file
|
@ -0,0 +1,154 @@
|
|||
import logging
|
||||
import logging.handlers as handlers
|
||||
import os
|
||||
from string import Formatter
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
from pathvalidate import sanitize_filename
|
||||
from tqdm import tqdm
|
||||
|
||||
from .constants import LOG_DIR, TIDAL_COVER_URL
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def safe_get(d: dict, *keys, default=None):
|
||||
"""A replacement for chained `get()` statements on dicts:
|
||||
>>> d = {'foo': {'bar': 'baz'}}
|
||||
>>> _safe_get(d, 'baz')
|
||||
None
|
||||
>>> _safe_get(d, 'foo', 'bar')
|
||||
'baz'
|
||||
"""
|
||||
curr = d
|
||||
res = default
|
||||
for key in keys:
|
||||
res = curr.get(key, default)
|
||||
if res == default or not hasattr(res, "__getitem__"):
|
||||
return res
|
||||
else:
|
||||
curr = res
|
||||
return res
|
||||
|
||||
|
||||
def quality_id(bit_depth: Optional[int], sampling_rate: Optional[int]):
|
||||
"""Return a quality id in (5, 6, 7, 27) from bit depth and
|
||||
sampling rate. If None is provided, mp3/lossy is assumed.
|
||||
|
||||
:param bit_depth:
|
||||
:type bit_depth: Optional[int]
|
||||
:param sampling_rate:
|
||||
:type sampling_rate: Optional[int]
|
||||
"""
|
||||
if not (bit_depth or sampling_rate): # is lossy
|
||||
return 5
|
||||
|
||||
if bit_depth == 16:
|
||||
return 6
|
||||
|
||||
if bit_depth == 24:
|
||||
if sampling_rate <= 96:
|
||||
return 7
|
||||
|
||||
return 27
|
||||
|
||||
|
||||
def tqdm_download(url: str, filepath: str):
|
||||
"""Downloads a file with a progress bar.
|
||||
|
||||
:param url: url to direct download
|
||||
:param filepath: file to write
|
||||
:type url: str
|
||||
:type filepath: str
|
||||
"""
|
||||
# FIXME: add the conditional to the progress_bar bool
|
||||
logger.debug(f"Downloading {url} to {filepath}")
|
||||
r = requests.get(url, allow_redirects=True, stream=True)
|
||||
total = int(r.headers.get("content-length", 0))
|
||||
logger.debug(f"File size = {total}")
|
||||
try:
|
||||
with open(filepath, "wb") as file, tqdm(
|
||||
total=total, unit="iB", unit_scale=True, unit_divisor=1024
|
||||
) as bar:
|
||||
for data in r.iter_content(chunk_size=1024):
|
||||
size = file.write(data)
|
||||
bar.update(size)
|
||||
except Exception:
|
||||
try:
|
||||
os.remove(filepath)
|
||||
except OSError:
|
||||
pass
|
||||
raise
|
||||
|
||||
|
||||
def clean_format(formatter: str, format_info):
|
||||
"""Formats track or folder names sanitizing every formatter key.
|
||||
|
||||
:param formatter:
|
||||
:type formatter: str
|
||||
:param kwargs:
|
||||
"""
|
||||
fmt_keys = [i[1] for i in Formatter().parse(formatter) if i[1] is not None]
|
||||
|
||||
logger.debug("Formatter keys: %s", fmt_keys)
|
||||
|
||||
clean_dict = dict()
|
||||
for key in fmt_keys:
|
||||
if isinstance(format_info.get(key), (str, int, float)): # int for track numbers
|
||||
clean_dict[key] = sanitize_filename(str(format_info[key]))
|
||||
else:
|
||||
clean_dict[key] = "Unknown"
|
||||
|
||||
return formatter.format(**clean_dict)
|
||||
|
||||
|
||||
def tidal_cover_url(uuid, size):
|
||||
possibles = (80, 160, 320, 640, 1280)
|
||||
assert size in possibles, f"size must be in {possibles}"
|
||||
|
||||
return TIDAL_COVER_URL.format(uuid=uuid.replace("-", "/"), height=size, width=size)
|
||||
|
||||
|
||||
def init_log(
|
||||
path: Optional[str] = None, level: str = "DEBUG", rotate: str = "midnight"
|
||||
):
|
||||
"""
|
||||
Initialize a log instance with a stream handler and a rotating file handler.
|
||||
If a path is not set, fallback to the default app log directory.
|
||||
|
||||
:param path:
|
||||
:type path: Optional[str]
|
||||
:param level:
|
||||
:type level: str
|
||||
:param rotate:
|
||||
:type rotate: str
|
||||
"""
|
||||
if not path:
|
||||
os.makedirs(LOG_DIR, exist_ok=True)
|
||||
path = os.path.join(LOG_DIR, "qobuz_dl.log")
|
||||
|
||||
logger = logging.getLogger()
|
||||
level = logging.getLevelName(level)
|
||||
logger.setLevel(level)
|
||||
|
||||
formatter = logging.Formatter(
|
||||
fmt="%(asctime)s - %(module)s.%(funcName)s.%(levelname)s: %(message)s",
|
||||
datefmt="%H:%M:%S",
|
||||
)
|
||||
|
||||
rotable = handlers.TimedRotatingFileHandler(path, when=rotate)
|
||||
printable = logging.StreamHandler()
|
||||
|
||||
rotable.setFormatter(formatter)
|
||||
printable.setFormatter(formatter)
|
||||
|
||||
logger.addHandler(printable)
|
||||
logger.addHandler(rotable)
|
||||
|
||||
logging.getLogger("urllib3").setLevel(logging.WARNING)
|
||||
logging.getLogger("tidal_api").setLevel(logging.WARNING)
|
||||
|
||||
|
||||
def capitalize(s: str) -> str:
|
||||
return s[0].upper() + s[1:]
|
Loading…
Add table
Add a link
Reference in a new issue