Add -q <search_query> command line argument (#511)

* Add -s <search_term> command line argument

* add final newline

* Format and lint

* Update README

* Update no results test to use random query

---------

Co-authored-by: 7x11x13 <x7x11x13@gmail.com>
This commit is contained in:
Mark Henry 2024-08-14 09:45:16 -07:00 committed by GitHub
parent 091596c282
commit e06cc9c685
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 80 additions and 3 deletions

View File

@ -45,6 +45,7 @@ scdl me -f
-h --help Show this screen -h --help Show this screen
--version Show version --version Show version
-l [url] URL can be track/playlist/user -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 -n [maxtracks] Download the n last tracks of a playlist according to the creation date
-a Download all tracks of user (including reposts) -a Download all tracks of user (including reposts)
-t Download all uploads of a user (no reposts) -t Download all uploads of a user (no reposts)

View File

@ -1,9 +1,9 @@
"""scdl allows you to download music from Soundcloud """scdl allows you to download music from Soundcloud
Usage: Usage:
scdl (-l <track_url> | me) [-a | -f | -C | -t | -p | -r][-c | --force-metadata] scdl (-l <track_url> | -s <search_query> | me) [-a | -f | -C | -t | -p | -r]
[-n <maxtracks>][-o <offset>][--hidewarnings][--debug | --error][--path <path>] [-c | --force-metadata][-n <maxtracks>][-o <offset>][--hidewarnings][--debug | --error]
[--addtofile][--addtimestamp][--onlymp3][--hide-progress][--min-size <size>] [--path <path>][--addtofile][--addtimestamp][--onlymp3][--hide-progress][--min-size <size>]
[--max-size <size>][--remove][--no-album-tag][--no-playlist-folder] [--max-size <size>][--remove][--no-album-tag][--no-playlist-folder]
[--download-archive <file>][--sync <file>][--extract-artist][--flac][--original-art] [--download-archive <file>][--sync <file>][--extract-artist][--flac][--original-art]
[--original-name][--original-metadata][--no-original][--only-original] [--original-name][--original-metadata][--no-original][--only-original]
@ -19,6 +19,7 @@ Options:
-h --help Show this screen -h --help Show this screen
--version Show version --version Show version
-l [url] URL can be track/playlist/user -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 -n [maxtracks] Download the n last tracks of a playlist according to the
creation date creation date
-a Download all tracks of user (including reposts) -a Download all tracks of user (including reposts)
@ -191,6 +192,7 @@ class SCDLArgs(TypedDict):
remove: bool remove: bool
strict_playlist: bool strict_playlist: bool
sync: Optional[str] sync: Optional[str]
s: Optional[str]
t: bool t: bool
@ -366,6 +368,14 @@ def main() -> None:
assert me is not None assert me is not None
arguments["-l"] = me.permalink_url 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"]) arguments["-l"] = validate_url(client, arguments["-l"])
if arguments["--download-archive"]: if arguments["--download-archive"]:
@ -439,6 +449,23 @@ def validate_url(client: SoundCloud, url: str) -> str:
sys.exit(1) 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: def get_config(config_file: pathlib.Path) -> configparser.ConfigParser:
"""Gets config from scdl.cfg""" """Gets config from scdl.cfg"""
config = configparser.ConfigParser() config = configparser.ConfigParser()

49
tests/test_search.py Normal file
View File

@ -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,
)