From 43890f9336f4dd439a46990b0987a1e7f9542242 Mon Sep 17 00:00:00 2001 From: Jason Butler Date: Fri, 26 Jul 2024 20:48:11 +0100 Subject: [PATCH] Added '--add-description' option (#459) * Added '--add-description' option This new option will add the track description to a txt file (using the same filename as the music file). Some music players will display this text whilst the track is playing - great for tracklists on DJ mixes and podcasts. * Added subfolder switch * Revert: Added subfolder switch Accidently pushed to my branch by mistake - changes reverted * Fix lint errors * Add test for description file * Fix tests for pull requests --------- Co-authored-by: 7x11x13 --- README.md | 1 + scdl/scdl.py | 21 +++++++++++++++++++++ tests/test_track.py | 24 ++++++++++++++++++++++++ tests/utils.py | 3 +-- 4 files changed, 47 insertions(+), 2 deletions(-) mode change 100755 => 100644 README.md diff --git a/README.md b/README.md old mode 100755 new mode 100644 index d22f086..51a4918 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ scdl me -f --auth-token [token] Specify the auth token to use --overwrite Overwrite file if it already exists --strict-playlist Abort playlist downloading if one track fails to download +--add-description Adds the description to a seperate txt file (can be read by some players) --no-playlist Skip downloading playlists --opus Prefer downloading opus streams over mp3 streams ``` diff --git a/scdl/scdl.py b/scdl/scdl.py index 820cc2e..bb0c429 100644 --- a/scdl/scdl.py +++ b/scdl/scdl.py @@ -9,6 +9,7 @@ [--original-name][--original-metadata][--no-original][--only-original] [--name-format ][--strict-playlist][--playlist-name-format ] [--client-id ][--auth-token ][--overwrite][--no-playlist][--opus] + [--add-description] scdl -h | --help scdl --version @@ -68,6 +69,7 @@ --overwrite Overwrite file if it already exists --strict-playlist Abort playlist downloading if one track fails to download --no-playlist Skip downloading playlists + --add-description Adds the description to a separate txt file --opus Prefer downloading opus streams over mp3 streams """ @@ -147,6 +149,7 @@ class SCDLArgs(TypedDict): C: bool a: bool + add_description: bool addtimestamp: bool addtofile: bool auth_token: Optional[str] @@ -1070,6 +1073,8 @@ def download_track( files_to_keep.append(filename) record_download_archive(track, kwargs) + if kwargs["add_description"]: + create_description_file(track.description, filename) to_stdout = is_downloading_to_stdout(kwargs) @@ -1111,6 +1116,22 @@ def can_convert(filename: str) -> bool: return "wav" in ext or "aif" in ext +def create_description_file(description: Optional[str], filename: str) -> None: + """ + Creates txt file containing the description + """ + desc = description or "" + if desc: + try: + description_filename = pathlib.Path(filename).with_suffix(".txt") + with open(description_filename, "w", encoding="utf-8") as f: + f.write(desc) + logger.info("Created description txt file") + except OSError as ioe: + logger.error("Error trying to write description txt file...") + logger.error(ioe) + + def already_downloaded( track: Union[BasicTrack, Track], title: str, diff --git a/tests/test_track.py b/tests/test_track.py index 44ae115..aa60739 100644 --- a/tests/test_track.py +++ b/tests/test_track.py @@ -7,6 +7,7 @@ from tests.utils import assert_not_track, assert_track, call_scdl_with_auth +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_original_download(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -54,6 +55,7 @@ def test_mp3_to_stdout(tmp_path: Path) -> None: assert_track(tmp_path, "track.mp3") +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_flac_to_stdout(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -73,6 +75,7 @@ def test_flac_to_stdout(tmp_path: Path) -> None: assert_track(tmp_path, "track.flac", "copy", "saves", None) +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_flac(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -86,6 +89,7 @@ def test_flac(tmp_path: Path) -> None: assert_track(tmp_path, "track.flac", "copy", "saves", None) +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_m4a(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -163,6 +167,7 @@ def test_original_art(tmp_path: Path) -> None: assert_track(tmp_path, "track.mp3", expected_artwork_len=3409) +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_original_name(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -176,6 +181,7 @@ def test_original_name(tmp_path: Path) -> None: assert_track(tmp_path, "original.wav", check_metadata=False) +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_original_metadata(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -189,6 +195,7 @@ def test_original_metadata(tmp_path: Path) -> None: assert_track(tmp_path, "track.wav", "og title", "og artist", "og genre", 0) +@pytest.mark.skipif(not os.getenv("AUTH_TOKEN"), reason="No auth token specified") def test_force_metadata(tmp_path: Path) -> None: os.chdir(tmp_path) r = call_scdl_with_auth( @@ -378,3 +385,20 @@ def test_download_archive(tmp_path: Path) -> None: ) assert r.returncode == 1 assert "already exists" in r.stderr + + +def test_description_file(tmp_path: Path) -> None: + os.chdir(tmp_path) + r = call_scdl_with_auth( + "-l", + "https://soundcloud.com/one-thousand-and-one/test-track", + "--name-format", + "track", + "--onlymp3", + "--add-description", + ) + assert r.returncode == 0 + desc_file = Path("./track.txt") + assert desc_file.exists() + with open(desc_file, encoding="utf-8") as f: + assert f.read().splitlines() == ["test description:", "9439290883"] diff --git a/tests/utils.py b/tests/utils.py index eaa5847..d4a5da4 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -13,8 +13,7 @@ def call_scdl_with_auth( *args: str, encoding: Optional[str] = "utf-8", ) -> subprocess.CompletedProcess: - auth_token = os.getenv("AUTH_TOKEN") - assert auth_token + auth_token = os.getenv("AUTH_TOKEN", "") args = ("scdl", *args, f"--auth-token={auth_token}", f"--client-id={client_id}") return subprocess.run( args,