Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add -s <search_query> command line argument #511

Merged
merged 5 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
33 changes: 30 additions & 3 deletions scdl/scdl.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""scdl allows you to download music from Soundcloud

Usage:
scdl (-l <track_url> | me) [-a | -f | -C | -t | -p | -r][-c | --force-metadata]
[-n <maxtracks>][-o <offset>][--hidewarnings][--debug | --error][--path <path>]
[--addtofile][--addtimestamp][--onlymp3][--hide-progress][--min-size <size>]
scdl (-l <track_url> | -s <search_query> | me) [-a | -f | -C | -t | -p | -r]
[-c | --force-metadata][-n <maxtracks>][-o <offset>][--hidewarnings][--debug | --error]
[--path <path>][--addtofile][--addtimestamp][--onlymp3][--hide-progress][--min-size <size>]
[--max-size <size>][--remove][--no-album-tag][--no-playlist-folder]
[--download-archive <file>][--sync <file>][--extract-artist][--flac][--original-art]
[--original-name][--original-metadata][--no-original][--only-original]
Expand All @@ -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)
Expand Down Expand Up @@ -191,6 +192,7 @@ class SCDLArgs(TypedDict):
remove: bool
strict_playlist: bool
sync: Optional[str]
s: Optional[str]
t: bool


Expand Down Expand Up @@ -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"]:
Expand Down Expand Up @@ -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()
Expand Down
49 changes: 49 additions & 0 deletions tests/test_search.py
Original file line number Diff line number Diff line change
@@ -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,
)
Loading