mirror of
https://github.com/nathom/streamrip.git
synced 2024-09-19 11:18:45 -04:00
Merge branch 'dev'
This commit is contained in:
commit
d00e6e2f48
5 changed files with 45 additions and 27 deletions
|
@ -133,29 +133,23 @@ class DeezerDownloadable(Downloadable):
|
||||||
blowfish_key,
|
blowfish_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert self.chunk_size == 2048 * 3
|
buf = bytearray()
|
||||||
|
async for data, _ in resp.content.iter_chunks():
|
||||||
|
buf += data
|
||||||
|
callback(len(data))
|
||||||
|
|
||||||
# Write data from server to tempfile because there's no
|
async with aiofiles.open(path, "wb") as audio:
|
||||||
# efficient way to guarantee a fixed chunk size for all iterations
|
buflen = len(buf)
|
||||||
# in async
|
for i in range(0, buflen, self.chunk_size):
|
||||||
async with aiofiles.tempfile.TemporaryFile("wb+") as tmp:
|
data = buf[i : min(i + self.chunk_size, buflen - 1)]
|
||||||
async for chunk in resp.content.iter_chunks():
|
if len(data) >= 2048:
|
||||||
data, _ = chunk
|
decrypted_chunk = (
|
||||||
await tmp.write(data)
|
self._decrypt_chunk(blowfish_key, data[:2048])
|
||||||
callback(len(data))
|
+ data[2048:]
|
||||||
|
)
|
||||||
await tmp.seek(0)
|
else:
|
||||||
async with aiofiles.open(path, "wb") as audio:
|
decrypted_chunk = data
|
||||||
while chunk := await tmp.read(self.chunk_size):
|
await audio.write(decrypted_chunk)
|
||||||
if len(chunk) >= 2048:
|
|
||||||
decrypted_chunk = (
|
|
||||||
self._decrypt_chunk(blowfish_key, chunk[:2048])
|
|
||||||
+ chunk[2048:]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
decrypted_chunk = chunk
|
|
||||||
|
|
||||||
await audio.write(decrypted_chunk)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _decrypt_chunk(key, data):
|
def _decrypt_chunk(key, data):
|
||||||
|
|
|
@ -161,7 +161,7 @@ add_singles_to_folder = false
|
||||||
folder_format = "{albumartist} - {title} ({year}) [{container}] [{bit_depth}B-{sampling_rate}kHz]"
|
folder_format = "{albumartist} - {title} ({year}) [{container}] [{bit_depth}B-{sampling_rate}kHz]"
|
||||||
# Available keys: "tracknumber", "artist", "albumartist", "composer", "title",
|
# Available keys: "tracknumber", "artist", "albumartist", "composer", "title",
|
||||||
# and "albumcomposer", "explicit"
|
# and "albumcomposer", "explicit"
|
||||||
track_format = "{tracknumber}. {artist} - {title}{explicit}"
|
track_format = "{tracknumber:02}. {artist} - {title}{explicit}"
|
||||||
# Only allow printable ASCII characters in filenames.
|
# Only allow printable ASCII characters in filenames.
|
||||||
restrict_characters = false
|
restrict_characters = false
|
||||||
# Truncate the filename if it is greater than this number of characters
|
# Truncate the filename if it is greater than this number of characters
|
||||||
|
|
|
@ -7,6 +7,7 @@ from .. import progress
|
||||||
from ..client import Client
|
from ..client import Client
|
||||||
from ..config import Config
|
from ..config import Config
|
||||||
from ..db import Database
|
from ..db import Database
|
||||||
|
from ..exceptions import NonStreamableError
|
||||||
from ..filepath_utils import clean_filepath
|
from ..filepath_utils import clean_filepath
|
||||||
from ..metadata import AlbumMetadata
|
from ..metadata import AlbumMetadata
|
||||||
from ..metadata.util import get_album_track_ids
|
from ..metadata.util import get_album_track_ids
|
||||||
|
@ -50,7 +51,14 @@ class PendingAlbum(Pending):
|
||||||
db: Database
|
db: Database
|
||||||
|
|
||||||
async def resolve(self) -> Album | None:
|
async def resolve(self) -> Album | None:
|
||||||
resp = await self.client.get_metadata(self.id, "album")
|
try:
|
||||||
|
resp = await self.client.get_metadata(self.id, "album")
|
||||||
|
except NonStreamableError as e:
|
||||||
|
logger.error(
|
||||||
|
f"Album {self.id} not available to stream on {self.client.source} ({e})",
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
meta = AlbumMetadata.from_album_resp(resp, self.client.source)
|
meta = AlbumMetadata.from_album_resp(resp, self.client.source)
|
||||||
if meta is None:
|
if meta is None:
|
||||||
logger.error(
|
logger.error(
|
||||||
|
|
|
@ -7,6 +7,7 @@ from ..client import Client
|
||||||
from ..config import Config, QobuzDiscographyFilterConfig
|
from ..config import Config, QobuzDiscographyFilterConfig
|
||||||
from ..console import console
|
from ..console import console
|
||||||
from ..db import Database
|
from ..db import Database
|
||||||
|
from ..exceptions import NonStreamableError
|
||||||
from ..metadata import ArtistMetadata
|
from ..metadata import ArtistMetadata
|
||||||
from .album import Album, PendingAlbum
|
from .album import Album, PendingAlbum
|
||||||
from .media import Media, Pending
|
from .media import Media, Pending
|
||||||
|
@ -180,8 +181,15 @@ class PendingArtist(Pending):
|
||||||
config: Config
|
config: Config
|
||||||
db: Database
|
db: Database
|
||||||
|
|
||||||
async def resolve(self) -> Artist:
|
async def resolve(self) -> Artist | None:
|
||||||
resp = await self.client.get_metadata(self.id, "artist")
|
try:
|
||||||
|
resp = await self.client.get_metadata(self.id, "artist")
|
||||||
|
except NonStreamableError as e:
|
||||||
|
logger.error(
|
||||||
|
f"Artist {self.id} not available to stream on {self.client.source} ({e})",
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
meta = ArtistMetadata.from_resp(resp, self.client.source)
|
meta = ArtistMetadata.from_resp(resp, self.client.source)
|
||||||
albums = [
|
albums = [
|
||||||
PendingAlbum(album_id, self.client, self.config, self.db)
|
PendingAlbum(album_id, self.client, self.config, self.db)
|
||||||
|
|
|
@ -147,7 +147,14 @@ class PendingPlaylist(Pending):
|
||||||
db: Database
|
db: Database
|
||||||
|
|
||||||
async def resolve(self) -> Playlist | None:
|
async def resolve(self) -> Playlist | None:
|
||||||
resp = await self.client.get_metadata(self.id, "playlist")
|
try:
|
||||||
|
resp = await self.client.get_metadata(self.id, "playlist")
|
||||||
|
except NonStreamableError as e:
|
||||||
|
logger.error(
|
||||||
|
f"Playlist {self.id} not available to stream on {self.client.source} ({e})",
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
meta = PlaylistMetadata.from_resp(resp, self.client.source)
|
meta = PlaylistMetadata.from_resp(resp, self.client.source)
|
||||||
name = meta.name
|
name = meta.name
|
||||||
parent = self.config.session.downloads.folder
|
parent = self.config.session.downloads.folder
|
||||||
|
@ -261,6 +268,7 @@ class PendingLastfmPlaylist(Pending):
|
||||||
if that fails.
|
if that fails.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
----
|
||||||
query (str): Query to search
|
query (str): Query to search
|
||||||
s (Status):
|
s (Status):
|
||||||
callback: function to call after each query completes
|
callback: function to call after each query completes
|
||||||
|
|
Loading…
Reference in a new issue