Make Deezer/Deezloader transitions smoother

This commit is contained in:
nathom 2021-07-28 21:41:21 -07:00
parent 96b15d9917
commit aac254516f
5 changed files with 1273 additions and 1253 deletions

View file

@ -38,12 +38,20 @@ refresh_token = ""
# in again using `rip config --tidal`
token_expiry = ""
# Doesn't require login
[deezer]
# 0, 1, or 2
# This only applies to paid Deezer subscriptions. Those using deezloader
# are automatically limited to quality = 1
quality = 2
use_deemix_server = true
# An authentication cookie that allows streamrip to use your Deezer account
# See [ADD LINK] for instructions on how to find this
arl = ""
# This allows for free 320kbps MP3 downloads from Deezer
# If an arl is provided, deezloader is never used
use_deezloader = true
# This warns you when the paid deezer account is not logged in and rip falls
# back to deezloader, which is unreliable
deezloader_warnings = true
[soundcloud]
# Only 0 is available for now

View file

@ -35,6 +35,7 @@ from streamrip.clients import (
)
from .config import Config
from streamrip.constants import MEDIA_TYPES
from streamrip.utils import set_progress_bar_theme, TQDM_DEFAULT_THEME
from .constants import (
URL_REGEX,
SOUNDCLOUD_URL_REGEX,
@ -56,7 +57,12 @@ from streamrip.exceptions import (
NoResultsFound,
ParsingError,
)
from .utils import extract_deezer_dynamic_link, extract_interpreter_url
from .utils import (
extract_deezer_dynamic_link,
extract_interpreter_url,
)
from .exceptions import DeezloaderFallback
logger = logging.getLogger("streamrip")
@ -191,8 +197,6 @@ class RipCore(list):
:param item_id:
:type item_id: str
"""
self.assert_creds(source)
client = self.get_client(source)
if media_type not in MEDIA_TYPES:
@ -340,8 +344,11 @@ class RipCore(list):
"""
client = self.clients[source]
if not client.logged_in:
self.assert_creds(source)
try:
self.login(client)
except DeezloaderFallback:
client = self.clients["deezloader"]
return client
def login(self, client):
@ -350,16 +357,27 @@ class RipCore(list):
:param client:
"""
creds = self.config.creds(client.source)
if client.source == "deezer" and creds["arl"] == "":
if self.config.session["deezer"]["deezloader_warnings"]:
click.secho(
"Falling back to Deezloader (max 320kbps MP3). If you have a subscription, run ",
nl=False,
fg="yellow",
)
click.secho("rip config --deezer ", nl=False, bold=True)
click.secho("to download FLAC files.\n\n", fg="yellow")
raise DeezloaderFallback
while True:
try:
client.login(**creds)
break
except AuthenticationError:
click.secho("Invalid credentials, try again.")
click.secho("Invalid credentials, try again.", fg="yellow")
self.prompt_creds(client.source)
creds = self.config.creds(client.source)
except MissingCredentials:
logger.debug("Credentials are missing. Prompting..")
logger.debug("Credentials are missing. Prompting..", fg="yellow")
self.prompt_creds(client.source)
creds = self.config.creds(client.source)
@ -571,13 +589,6 @@ class RipCore(list):
else page["albums"]["items"]
)
for i, item in enumerate(tracklist):
if item_id := str(item["id"]) in self.db:
click.secho(
f"ID {item_id} already logged in database. Skipping.",
fg="magenta",
)
continue
yield MEDIA_CLASS[ # type: ignore
media_type if media_type != "featured" else "album"
].from_api(item, client)
@ -811,8 +822,20 @@ class RipCore(list):
fg="green",
)
elif source == "deezer":
click.secho("Enter Deezer ARL: ", fg="green")
self.config.file["deezer"]["arl"] = input()
click.secho(
"If you're not sure how to find the ARL cookie, see the instructions at ",
italic=True,
nl=False,
dim=True,
)
click.secho(
"https://github.com/nathom/streamrip/wiki/Finding-your-Deezer-ARL-Cookie",
underline=True,
italic=True,
fg="blue",
)
self.config.file["deezer"]["arl"] = input(click.style("ARL: ", fg="green"))
self.config.save()
click.secho(
f'Credentials saved to config file at "{self.config._path}"',
@ -821,28 +844,6 @@ class RipCore(list):
else:
raise Exception
def assert_creds(self, source: str):
"""Ensure that the credentials for `source` are valid.
:param source:
:type source: str
"""
assert source in (
"qobuz",
"tidal",
"deezer",
"soundcloud",
), f"Invalid source {source}"
if source == "soundcloud":
return
if source == "qobuz" and (
self.config.file[source]["email"] is None
or self.config.file[source]["password"] is None
):
self.prompt_creds(source)
def _config_updating_message(self):
click.secho(
"Updating config file... Some settings may be lost. Please run the "

2
rip/exceptions.py Normal file
View file

@ -0,0 +1,2 @@
class DeezloaderFallback(Exception):
pass

View file

@ -1036,8 +1036,9 @@ class TidalClient(Client):
params["countryCode"] = self.country_code
params["limit"] = 100
r = self.session.get(f"{TIDAL_BASE}/{path}", params=params).json()
return r
r = self.session.get(f"{TIDAL_BASE}/{path}", params=params)
r.raise_for_status()
return r.json()
def _get_video_stream_url(self, video_id: str) -> str:
"""Get the HLS video stream url.

View file

@ -280,12 +280,20 @@ class Track(Media):
try:
download_url = dl_info["url"]
except KeyError as e:
if restrictions := dl_info["restrictions"]:
# Turn CamelCase code into a readable sentence
words = re.findall(r"([A-Z][a-z]+)", restrictions[0]["code"])
raise NonStreamable(
words[0] + " " + " ".join(map(str.lower, words[1:])) + "."
)
click.secho(f"Panic: {e} dl_info = {dl_info}", fg="red")
raise NonStreamable
_quick_download(download_url, self.path, desc=self._progress_desc)
elif isinstance(self.client, DeezloaderClient):
tqdm_download(dl_info["url"], self.path, desc=self._progress_desc)
_quick_download(dl_info["url"], self.path, desc=self._progress_desc)
elif self.client.source == "deezer":
# We can only find out if the requested quality is available
@ -1205,7 +1213,8 @@ class Tracklist(list):
"""
click.secho(
f"\n\nDownloading {self.title} ({self.__class__.__name__})\n",
fg="blue",
fg="magenta",
bold=True,
)
@staticmethod
@ -1345,7 +1354,6 @@ class Album(Tracklist, Media):
# Generate the folder name
self.folder_format = kwargs.get("folder_format", FOLDER_FORMAT)
self.quality = min(kwargs.get("quality", 3), self.client.max_quality)
print(f"{self.quality=} {self.client.max_quality = }")
self.folder = self._get_formatted_folder(
kwargs.get("parent_folder", "StreamripDownloads"), self.quality