diff --git a/pyproject.toml b/pyproject.toml index eac7bf6..73dfb6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,16 +1,23 @@ [project] name = "qobuz-dl-remote" version = "0.1.0" -authors = [ -{name = "Christoph Stahl", email = "christoph.stahl@tu-dortmund.de"} -] description = "Add your description here" readme = "README.md" +authors = [ + { name = "Christoph Stahl", email = "christoph.stahl@tu-dortmund.de" } +] requires-python = ">=3.10" dependencies = [ - "music-tag>=0.4.3", + "musicbrainzngs>=0.7.1", "mutagen>=1.47.0", "pillow>=11.3.0", "requests>=2.32.4", "tqdm>=4.67.1", ] + +[project.scripts] +qobuz-dl-remote = "qobuz_dl_remote.main:main" + +[build-system] +requires = ["uv_build>=0.8.4,<0.9.0"] +build-backend = "uv_build" diff --git a/qobuz_dl_remote/__init__.py b/src/qobuz_dl_remote/__init__.py similarity index 100% rename from qobuz_dl_remote/__init__.py rename to src/qobuz_dl_remote/__init__.py diff --git a/qobuz_dl_remote/main.py b/src/qobuz_dl_remote/main.py similarity index 69% rename from qobuz_dl_remote/main.py rename to src/qobuz_dl_remote/main.py index ac24901..30caab1 100755 --- a/qobuz_dl_remote/main.py +++ b/src/qobuz_dl_remote/main.py @@ -1,16 +1,15 @@ -#!/usr/bin/env python3 +import datetime import os +from dataclasses import dataclass +from io import BytesIO from typing import Any, Literal +from configparser import ConfigParser +from argparse import ArgumentParser + import requests import tqdm - -import music_tag -import sys -from dataclasses import dataclass -import datetime - -QOBUZ_API_BASE = "https://us.qobuz.squid.wtf/api" -QUALITY = 27 +from mutagen.flac import FLAC, Picture +from PIL import Image @dataclass @@ -93,12 +92,12 @@ class Album: class Qobuz: - def __init__(self, api_base=QOBUZ_API_BASE, quality: int = QUALITY) -> None: + def __init__(self, api_base, quality: int) -> None: self.api_base = api_base self.quality = quality def get_download_url(self, track_id: str) -> str: - url = f"{QOBUZ_API_BASE}/download-music" + url = f"{self.api_base}/download-music" result = requests.get( url, params={"track_id": track_id, "quality": self.quality} ) @@ -110,24 +109,35 @@ class Qobuz: def download_track(self, track: Track, filename: str, dest: str) -> None: download_url = self.get_download_url(track.id) + dest_path = os.path.join(dest, filename) response = requests.get(download_url, stream=True) if response.status_code == 200: total_size = int(response.headers.get("content-length", 0)) with tqdm.tqdm( total=total_size, unit="B", unit_scale=True, desc=filename ) as pbar: - with open(os.path.join(dest, filename), "wb") as file: + with open(dest_path, "wb") as file: for chunk in response.iter_content(chunk_size=8192): file.write(chunk) pbar.update(len(chunk)) # Set metadata using mutagen - audio = music_tag.load_file(filename) - audio["tracktitle"] = track.title + audio = FLAC(dest_path) + audio["title"] = track.title audio["artist"] = track.album.artist audio["tracknumber"] = str(track.nr) audio["album"] = track.album.title - audio["year"] = track.album.release_date.year - audio["artwork"] = track.album.cover_data + audio["release_date"] = track.album.release_date.isoformat() + if track.album.cover_data is not None: + picture = Picture() + pil_image = Image.open(BytesIO(track.album.cover_data)) + picture.type = 3 # Front cover + picture.data = track.album.cover_data + picture.mime = pil_image.get_format_mimetype() + picture.desc = "Cover" + picture.width = pil_image.width + picture.height = pil_image.height + picture.depth = len(pil_image.getbands()) * 8 + audio.add_picture(picture) audio.save() print(f"Downloaded {filename}") @@ -167,11 +177,42 @@ class Qobuz: self.download_album(album, f"{album.artist} - {album.title}") +def get_config() -> ConfigParser: + config = ConfigParser() + if os.path.exists("config.ini"): + config_file = "config.ini" + else: + config_file = os.path.expanduser("~/.config/qobuz_dl_remote/config.ini") + if not os.path.exists(config_file): + raise FileNotFoundError(f"Config file not found: {config_file}") + config.read(config_file) + return config + + def main() -> None: - # trackid = sys.argv[1] - # filename = sys.argv[2] - query = sys.argv[1] - qb = Qobuz() + config = get_config() + base_url = config.get("qobuz", "api_base") + if not base_url: + print("No API base URL configured, please set api_base under [qobuz].") + quality = config.getint("qobuz", "quality", fallback=27) + + parser = ArgumentParser(description="Qobuz Remote Downloader") + parser.add_argument( + "--type", + "-t", + type=str, + choices=["album", "discography"], + default="album", + help="Type of search to perform", + ) + parser.add_argument( + "query", type=str, help="Search query for the album to download" + ) + parser.add_argument("--beet", "-b", action="store_true", help="Import into Beet") + args = parser.parse_args() + + query = args.query + qb = Qobuz(api_base=base_url, quality=quality) print(qb.search_and_download(query)) diff --git a/uv.lock b/uv.lock index f711a2f..101a55c 100644 --- a/uv.lock +++ b/uv.lock @@ -94,13 +94,13 @@ wheels = [ ] [[package]] -name = "music-tag" -version = "0.4.3" +name = "musicbrainzngs" +version = "0.7.1" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mutagen" }, +sdist = { url = "https://files.pythonhosted.org/packages/0a/67/3e74ae93d90ceeba72ed1a266dd3ca9abd625f315f0afd35f9b034acedd1/musicbrainzngs-0.7.1.tar.gz", hash = "sha256:ab1c0100fd0b305852e65f2ed4113c6de12e68afd55186987b8ed97e0f98e627", size = 117469, upload-time = "2020-01-11T17:38:47.581Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/fd/cef7b2580436910ccd2f8d3deec0f3c81743e15c0eb5b97dde3fbf33c0c8/musicbrainzngs-0.7.1-py2.py3-none-any.whl", hash = "sha256:e841a8f975104c0a72290b09f59326050194081a5ae62ee512f41915090e1a10", size = 25289, upload-time = "2020-01-11T17:38:45.469Z" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fc/f4/ebcdd2fc9bfaf569b795250090e4f4088dc65a5a3e32c53baa9bfc3fc296/music-tag-0.4.3.tar.gz", hash = "sha256:0aab6e6eeda8df0f5316ec2d2190bd74561b7e03562ab091ce8d5687cdbcfff6", size = 23153, upload-time = "2021-06-05T17:20:23.552Z" } [[package]] name = "mutagen" @@ -216,9 +216,9 @@ wheels = [ [[package]] name = "qobuz-dl-remote" version = "0.1.0" -source = { virtual = "." } +source = { editable = "." } dependencies = [ - { name = "music-tag" }, + { name = "musicbrainzngs" }, { name = "mutagen" }, { name = "pillow" }, { name = "requests" }, @@ -227,7 +227,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "music-tag", specifier = ">=0.4.3" }, + { name = "musicbrainzngs", specifier = ">=0.7.1" }, { name = "mutagen", specifier = ">=1.47.0" }, { name = "pillow", specifier = ">=11.3.0" }, { name = "requests", specifier = ">=2.32.4" },