diff --git a/.mypy.ini b/.mypy.ini index 195a7cc..9f87719 100644 --- a/.mypy.ini +++ b/.mypy.ini @@ -21,3 +21,6 @@ ignore_missing_imports = True [mypy-tomlkit.*] ignore_missing_imports = True + +[mypy-PIL.*] +ignore_missing_imports = True diff --git a/poetry.lock b/poetry.lock index 025f09c..9d0d23b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -71,6 +71,14 @@ python-versions = ">=3.5" [package.dependencies] windows-curses = {version = "*", markers = "platform_system == \"Windows\""} +[[package]] +name = "pillow" +version = "8.3.0" +description = "Python Imaging Library (Fork)" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "requests" version = "2.25.1" @@ -120,7 +128,7 @@ telegram = ["requests"] [[package]] name = "urllib3" -version = "1.26.5" +version = "1.26.6" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false @@ -142,7 +150,7 @@ python-versions = "*" [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "a32e56def426809c20924e370d316663d2369853defcd590ee0c78aaef237ad3" +content-hash = "fe85433e74f85333932d145aa003b13164c786000da6083cb761f0823ebe2729" [metadata.files] certifi = [ @@ -177,6 +185,42 @@ pick = [ {file = "pick-1.0.0-py2.py3-none-any.whl", hash = "sha256:f32c8bd0fd943490c29e461a8168f4ac267247aaa6a7fc9dd327f97832842b5f"}, {file = "pick-1.0.0.tar.gz", hash = "sha256:03f13d4f5bfe74db4b969fb74c0ef110ec443978419d6c0f1f375a0d49539034"}, ] +pillow = [ + {file = "Pillow-8.3.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:333313bcc53a8a7359e98d5458dfe37bfa301da2fd0e0dc41f585ae0cede9181"}, + {file = "Pillow-8.3.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bccd0d604d814e9494f3bf3f077a23835580ed1743c5175581882e7dd1f178c3"}, + {file = "Pillow-8.3.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7beda44f177ee602aa27e0a297da1657d9572679522c8fb8b336b734653516e"}, + {file = "Pillow-8.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:94db5ea640330de0945b41dc77fb4847b4ab6e87149126c71b36b112e8400898"}, + {file = "Pillow-8.3.0-cp36-cp36m-win32.whl", hash = "sha256:856fcbc3201a6cabf0478daa0c0a1a8a175af7e5173e2084ddb91cc707a09dd1"}, + {file = "Pillow-8.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34ce3d993cb4ca840b1e31165b38cb19c64f64f822a8bc5565bde084baff3bdb"}, + {file = "Pillow-8.3.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:778a819c2d194e08d39d67ddb15ef0d32eba17bf7d0c2773e97bd221b2613a3e"}, + {file = "Pillow-8.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b42ea77f4e7374a67e1f27aaa9c62627dff681f67890e5b8f0c1e21b1500d9d2"}, + {file = "Pillow-8.3.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:53f6e4b73b3899015ac4aa95d99da0f48ea18a6d7c8db672e8bead3fb9570ef5"}, + {file = "Pillow-8.3.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fb91deb5121b6dde88599bcb3db3fdad9cf33ff3d4ccc5329ee1fe9655a2f7ff"}, + {file = "Pillow-8.3.0-cp37-cp37m-win32.whl", hash = "sha256:8f65d2a98f198e904dbe89ecb10862d5f0511367d823689039e17c4d011de11e"}, + {file = "Pillow-8.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:25f6564df21d15bcac142b4ed92b6c02e53557539f535f31c1f3bcc985484753"}, + {file = "Pillow-8.3.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:c2d78c8230bda5fc9f6b1d457c7f8f3432f4fe85bed86f80ba3ed73d59775a88"}, + {file = "Pillow-8.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:950e873ceefbd283cbe7bc5b648b832d1dcf89eeded6726ebec42bc7d67966c0"}, + {file = "Pillow-8.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1037288a22cc8ec9d2918a24ded733a1cc4342fd7f21d15d37e6bbe5fb4a7306"}, + {file = "Pillow-8.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:063d17a02a0170c2f880fbd373b2738b089c6adcbd1f7418667bc9e97524c11b"}, + {file = "Pillow-8.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:561339ed7c324bbcb29b5e4f4705c97df950785394b3ac181f5bf6a08088a672"}, + {file = "Pillow-8.3.0-cp38-cp38-win32.whl", hash = "sha256:331f8321418682386e4f0d0e6369f732053f95abddd2af4e1b1ef74a9537ef37"}, + {file = "Pillow-8.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:eccaefbd646022b5313ca4b0c5f1ae6e0d3a52ef66de64970ecf3f9b2a1be751"}, + {file = "Pillow-8.3.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:6f7517a220aca8b822e25b08b0df9546701a606a328da5bc057e5f32a3f9b07c"}, + {file = "Pillow-8.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cc8e926d6ffa65d0dddb871b7afe117f17bc045951e66afde60eb0eba923db9e"}, + {file = "Pillow-8.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:519b3b24dedc81876d893475bade1b92c4ce7c24b9b82224f0bd8daae682e039"}, + {file = "Pillow-8.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:72858a27dd7bd1c40f91c4f85db3b9f121c8412fd66573121febb00d074d0530"}, + {file = "Pillow-8.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:3251557c53c1ed0c345559afc02d2b0a0aa5788042e161366ed90b27bc322d3d"}, + {file = "Pillow-8.3.0-cp39-cp39-win32.whl", hash = "sha256:ce90aad0a3dc0f13a9ff0ab1f43bcbea436089b83c3fadbe37c6f1733b938bf1"}, + {file = "Pillow-8.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:490c9236ef4762733b6c2e1f1fcb37793cb9c57d860aa84d6994c990461882e5"}, + {file = "Pillow-8.3.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:aef0838f28328523e9e5f2c1852dd96fb85768deb0eb8f908c54dad0f44d2f6f"}, + {file = "Pillow-8.3.0-pp36-pypy36_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:713b762892efa8cd5d8dac24d16ac2d2dbf981963ed1b3297e79755f03f8cbb8"}, + {file = "Pillow-8.3.0-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cec702974f162026bf8de47f6f4b7ce9584a63c50002b38f195ee797165fea77"}, + {file = "Pillow-8.3.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:d9ef8119ce44f90d2f8ac7c58f7da480ada5151f217dc8da03681b73fc91dec3"}, + {file = "Pillow-8.3.0-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:fc25d59ecf23ea19571065306806a29c43c67f830f0e8a121303916ba257f484"}, + {file = "Pillow-8.3.0-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:28f184c0a65be098af412f78b0b6f3bbafd1614e1dc896e810d8357342a794b7"}, + {file = "Pillow-8.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:c3529fb98a40f89269175442c5ff4ef81d22e91b2bdcbd33833a350709b5130c"}, + {file = "Pillow-8.3.0.tar.gz", hash = "sha256:803606e206f3e366eea46b1e7ab4dac74cfac770d04de9c35319814e11e47c46"}, +] requests = [ {file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, {file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, @@ -194,8 +238,8 @@ tqdm = [ {file = "tqdm-4.61.1.tar.gz", hash = "sha256:24be966933e942be5f074c29755a95b315c69a91f839a29139bf26ffffe2d3fd"}, ] urllib3 = [ - {file = "urllib3-1.26.5-py2.py3-none-any.whl", hash = "sha256:753a0374df26658f99d826cfe40394a686d05985786d946fbe4165b5148f5a7c"}, - {file = "urllib3-1.26.5.tar.gz", hash = "sha256:a7acd0977125325f516bda9735fa7142b909a8d01e8b2e4c8108d0984e6e0098"}, + {file = "urllib3-1.26.6-py2.py3-none-any.whl", hash = "sha256:39fb8672126159acb139a7718dd10806104dec1e2f0f6c88aab05d17df10c8d4"}, + {file = "urllib3-1.26.6.tar.gz", hash = "sha256:f57b4c16c62fa2760b7e3d97c35b255512fb6b59a259730f36ba32ce9f8e342f"}, ] windows-curses = [ {file = "windows_curses-2.2.0-cp36-cp36m-win32.whl", hash = "sha256:1452d771ec6f9b3fef037da2b169196a9a12be4e86a6c27dd579adac70c42028"}, diff --git a/pyproject.toml b/pyproject.toml index 7a80f61..201cf56 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,6 +32,7 @@ pathvalidate = "^2.4.1" simple-term-menu = {version = "^1.2.1", platform = 'linux or darwin'} pick = {version = "^1.0.0", platform = 'win32 or cygwin'} windows-curses = {version = "^2.2.0", platform = 'win32 or cygwin'} +Pillow = "^8.3.0" [tool.poetry.urls] "Bug Reports" = "https://github.com/nathom/streamrip/issues" diff --git a/rip/config.toml b/rip/config.toml index 9da2d06..8f98b8f 100644 --- a/rip/config.toml +++ b/rip/config.toml @@ -94,6 +94,10 @@ embed = true # "original" images can be up to 30MB, and may fail embedding. # Using "large" is recommended. size = "large" +# 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. +max_width = 999999 +max_height = 999999 # Save the cover image at the highest quality as a seperate jpg file keep_hires_cover = true @@ -128,4 +132,4 @@ fallback_source = "deezer" check_for_updates = true # Metadata to identify this config file. Do not change. -version = "0.6.1" +version = "0.7" diff --git a/rip/core.py b/rip/core.py index 0cdae89..de5e601 100644 --- a/rip/core.py +++ b/rip/core.py @@ -217,6 +217,8 @@ class MusicDL(list): "video_downloads_folder" ], "add_singles_to_folder": filepaths["add_singles_to_folder"], + "max_artwork_width": int(artwork["max_width"]), + "max_artwork_height": int(artwork["max_height"]), } def download(self): diff --git a/streamrip/clients.py b/streamrip/clients.py index 2b42d6f..ccfd043 100644 --- a/streamrip/clients.py +++ b/streamrip/clients.py @@ -268,12 +268,14 @@ class QobuzClient(Client): extras = { "artist": "albums", "playlist": "tracks", - "label": "albums", # not tested + "label": "albums", } if media_type in extras: params.update({"extra": extras[media_type]}) + logger.debug("request params: %s", params) + epoint = f"{media_type}/get" response, status_code = self._api_request(epoint, params) diff --git a/streamrip/media.py b/streamrip/media.py index a162026..4dfe795 100644 --- a/streamrip/media.py +++ b/streamrip/media.py @@ -33,6 +33,7 @@ from .exceptions import ( from .metadata import TrackMetadata from .utils import ( clean_format, + downsize_image, get_cover_urls, decho, decrypt_mqa_file, @@ -173,7 +174,10 @@ class Track: decho(f"Track already exists: {self.final_path}", fg="magenta") return False - self.download_cover() # only downloads for playlists and singles + self.download_cover( + width=kwargs.get("max_artwork_width", 999999), + height=kwargs.get("max_artwork_height", 999999), + ) # only downloads for playlists and singles self.path = os.path.join(gettempdir(), f"{hash(self.id)}_{self.quality}.tmp") return True @@ -339,7 +343,7 @@ class Track: """ return click.style(f"Track {int(self.meta.tracknumber):02}", fg="blue") - def download_cover(self): + def download_cover(self, width=999999, height=999999): """Download the cover art, if cover_url is given.""" if not hasattr(self, "cover_url"): return False @@ -354,6 +358,7 @@ class Track: self.cover_path, desc=click.style("Cover", fg="cyan"), ) + downsize_image(self.cover_path, width, height) else: logger.debug("Cover already exists, skipping download") @@ -1248,6 +1253,12 @@ class Album(Tracklist): # large is about 600x600px which is guaranteed < 16.7 MB tqdm_download(self.cover_urls["large"], cover_path) + downsize_image( + cover_path, + kwargs.get("max_artwork_width", 999999), + kwargs.get("max_artwork_height", 999999), + ) + embed_cover = kwargs.get("embed_cover", True) # embed by default if self.client.source != "deezer" and embed_cover: # container generated when formatting folder name diff --git a/streamrip/utils.py b/streamrip/utils.py index f03f984..615f5e1 100644 --- a/streamrip/utils.py +++ b/streamrip/utils.py @@ -416,3 +416,26 @@ def get_cover_urls(resp: dict, source: str) -> dict: return cover_urls raise InvalidSourceError(source) + + +def downsize_image(filepath: str, width: int, height: int): + """Downsize an image. If either the width or the height is greater + than the image's width or height, that dimension will not be changed. + + :param filepath: + :type filepath: str + :param width: + :type width: int + :param height: + :type height: int + :raises: ValueError + """ + from PIL import Image + + image = Image.open(filepath) + + width = min(width, image.width) + height = min(height, image.height) + + resized_image = image.resize((width, height)) + resized_image.save(filepath)