Misc enhancements

This commit is contained in:
nathom 2021-04-16 11:38:22 -07:00
parent 02eb2cdc9a
commit 1253d20173
4 changed files with 42 additions and 11 deletions

View file

@ -241,6 +241,9 @@ class QobuzClient(Client):
epoint = f"{media_type}/get"
response, status_code = self._api_request(epoint, params)
if status_code != 200:
raise Exception(f'Error fetching metadata. "{response["message"]}"')
return response
def _api_search(self, query, media_type, limit=500) -> Generator:
@ -410,6 +413,8 @@ class TidalClient(Client):
source = "tidal"
max_quality = 3
# ----------- Public Methods --------------
def __init__(self):
self.logged_in = False
@ -461,7 +466,10 @@ class TidalClient(Client):
}
return self._api_request(f"search/{media_type}s", params=params)
def get_file_url(self, track_id, quality: int = 3):
def get_file_url(self, track_id, quality: int = 3, video=False):
if video:
return self._get_video_stream_url(track_id)
params = {
"audioquality": get_quality(min(quality, TIDAL_MAX_Q), self.source),
"playbackmode": "STREAM",
@ -492,6 +500,8 @@ class TidalClient(Client):
)
}
# ------------ Utilities to login -------------
def _login_new_user(self, launch=True):
login_link = f"https://{self._get_device_code()}"
@ -613,6 +623,15 @@ class TidalClient(Client):
self.access_token = token
self._update_authorization()
def _update_authorization(self):
self.session.headers.update(self.authorization)
@property
def authorization(self):
return {"authorization": f"Bearer {self.access_token}"}
# ------------- Fetch data ------------------
def _api_get(self, item_id: str, media_type: str) -> dict:
url = f"{media_type}s/{item_id}"
item = self._api_request(url)
@ -644,13 +663,22 @@ class TidalClient(Client):
r = self.session.get(f"{TIDAL_BASE}/{path}", params=params).json()
return r
def _get_video_stream_url(self, video_id) -> str:
params = {
"videoquality": "HIGH",
"playbackmode": "STREAM",
"assetpresentation": "FULL",
}
resp = self._api_request(
f"videos/{video_id}/playbackinfopostpaywall", params=params
)
manifest = json.loads(base64.b64decode(resp['manifest']).decode("utf-8"))
return manifest['urls'][0]
def _api_post(self, url, data, auth=None):
r = self.session.post(url, data=data, auth=auth, verify=False).json()
return r
def _update_authorization(self):
self.session.headers.update({"authorization": f"Bearer {self.access_token}"})
class SoundCloudClient(Client):
source = "soundcloud"

View file

@ -158,7 +158,8 @@ TIDAL_Q_MAP = {
DEEZER_MAX_Q = 6
AVAILABLE_QUALITY_IDS = (0, 1, 2, 3, 4)
MEDIA_TYPES = ("track", "album", "artist", "label", "playlist")
# video only for tidal
MEDIA_TYPES = {"track", "album", "artist", "label", "playlist", "video"}
# used to homogenize cover size keys
COVER_SIZES = ("thumbnail", "small", "large", "original")

View file

@ -10,6 +10,7 @@ import re
import shutil
import subprocess
from tempfile import gettempdir
from dataclasses import dataclass
from typing import Any, Generator, Iterable, Union
import click
@ -812,7 +813,7 @@ class Album(Tracklist):
return Playlist.from_api(resp, client)
info = cls._parse_get_resp(resp, client)
return cls(client, **info)
return cls(client, **info.asdict())
def _prepare_download(self, **kwargs):
self.folder_format = kwargs.get("folder_format", FOLDER_FORMAT)

View file

@ -3,6 +3,7 @@
import logging
import re
from typing import Generator, Hashable, Optional, Tuple, Union
from collections import OrderedDict
from .constants import (
COPYRIGHT,
@ -136,7 +137,7 @@ class TrackMetadata:
# Non-embedded information
self.version = resp.get("version")
self.cover_urls = resp.get("image")
self.cover_urls = OrderedDict(resp.get("image"))
self.cover_urls["original"] = self.cover_urls["large"].replace("600", "org")
self.streamable = resp.get("streamable", False)
self.bit_depth = resp.get("maximum_bit_depth")
@ -162,10 +163,10 @@ class TrackMetadata:
self.explicit = resp.get("explicit", False)
# 80, 160, 320, 640, 1280
uuid = resp.get("cover")
self.cover_urls = {
self.cover_urls = OrderedDict({
sk: tidal_cover_url(uuid, size)
for sk, size in zip(COVER_SIZES, (160, 320, 640, 1280))
}
})
self.streamable = resp.get("allowStreaming", False)
self.quality = TIDAL_Q_MAP[resp["audioQuality"]]
@ -185,13 +186,13 @@ class TrackMetadata:
self.explicit = bool(resp.get("parental_warning"))
self.quality = 2
self.bit_depth = 16
self.cover_urls = {
self.cover_urls = OrderedDict({
sk: resp.get(rk) # size key, resp key
for sk, rk in zip(
COVER_SIZES,
("cover", "cover_medium", "cover_large", "cover_xl"),
)
}
})
self.sampling_rate = 44100
self.streamable = True