diff --git a/README.md b/README.md index 51a4918..bff7897 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ scdl me -f -h --help Show this screen --version Show version -l [url] URL can be track/playlist/user +-s [search_query] Search for a track/playlist/user and use the first result -n [maxtracks] Download the n last tracks of a playlist according to the creation date -a Download all tracks of user (including reposts) -t Download all uploads of a user (no reposts) diff --git a/scdl/scdl.py b/scdl/scdl.py index 6738598..05d178c 100644 --- a/scdl/scdl.py +++ b/scdl/scdl.py @@ -1,9 +1,9 @@ """scdl allows you to download music from Soundcloud Usage: - scdl (-l | me) [-a | -f | -C | -t | -p | -r][-c | --force-metadata] - [-n ][-o ][--hidewarnings][--debug | --error][--path ] - [--addtofile][--addtimestamp][--onlymp3][--hide-progress][--min-size ] + scdl (-l | -s | me) [-a | -f | -C | -t | -p | -r] + [-c | --force-metadata][-n ][-o ][--hidewarnings][--debug | --error] + [--path ][--addtofile][--addtimestamp][--onlymp3][--hide-progress][--min-size ] [--max-size ][--remove][--no-album-tag][--no-playlist-folder] [--download-archive ][--sync ][--extract-artist][--flac][--original-art] [--original-name][--original-metadata][--no-original][--only-original] @@ -19,6 +19,7 @@ -h --help Show this screen --version Show version -l [url] URL can be track/playlist/user + -s [search_query] Search for a track/playlist/user and use the first result -n [maxtracks] Download the n last tracks of a playlist according to the creation date -a Download all tracks of user (including reposts) @@ -191,6 +192,7 @@ class SCDLArgs(TypedDict): remove: bool strict_playlist: bool sync: Optional[str] + s: Optional[str] t: bool @@ -366,6 +368,14 @@ def main() -> None: assert me is not None arguments["-l"] = me.permalink_url + if arguments["-s"]: + url = search_soundcloud(client, arguments["-s"]) + if url: + arguments["-l"] = url + else: + logger.error("Search failed. Exiting...") + sys.exit(1) + arguments["-l"] = validate_url(client, arguments["-l"]) if arguments["--download-archive"]: @@ -439,6 +449,23 @@ def validate_url(client: SoundCloud, url: str) -> str: sys.exit(1) +def search_soundcloud(client: SoundCloud, query: str) -> Optional[str]: + """Search SoundCloud and return the URL of the first result.""" + try: + results = list(client.search(query, limit=1)) + if results: + item = results[0] + logger.info(f"Search resolved to url {item.permalink_url}") + if isinstance(item, (Track, AlbumPlaylist, User)): + return item.permalink_url + logger.warning(f"Unexpected search result type: {type(item)}") + logger.error(f"No results found for query: {query}") + return None + except Exception as e: + logger.error(f"Error searching SoundCloud: {e}") + return None + + def get_config(config_file: pathlib.Path) -> configparser.ConfigParser: """Gets config from scdl.cfg""" config = configparser.ConfigParser() diff --git a/tests/test_search.py b/tests/test_search.py new file mode 100644 index 0000000..fa8df6e --- /dev/null +++ b/tests/test_search.py @@ -0,0 +1,49 @@ +import os +import secrets +from pathlib import Path + +from tests.utils import assert_track, call_scdl_with_auth + + +def test_search(tmp_path: Path) -> None: + os.chdir(tmp_path) + r = call_scdl_with_auth( + "-s", + "7x11x13-testing test track", + "--name-format", + "track", + "--onlymp3", + ) + assert r.returncode == 0 + assert_track(tmp_path, "track.mp3") + + +def test_search_no_results(tmp_path: Path) -> None: + os.chdir(tmp_path) + r = call_scdl_with_auth( + "-s", + f"this query should not return any results {secrets.token_hex(16)}", + "--name-format", + "track", + "--onlymp3", + ) + assert r.returncode == 1 + assert "No results found for query" in r.stderr + + +def test_search_playlist(tmp_path: Path) -> None: + os.chdir(tmp_path) + r = call_scdl_with_auth( + "-s", + "playlist1 7x11x13-testing", + "--playlist-name-format", + "{playlist[tracknumber]}_{title}", + "--onlymp3", + ) + assert r.returncode == 0 + assert_track(tmp_path / "playlist1", "1_OK Bye.mp3", check_metadata=False) + assert_track( + tmp_path / "playlist1", + "2_Wan Bushi - Eurodance Vibes (part 1+2+3).mp3", + check_metadata=False, + )