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 -q <search_query> command line argument [develop] #512

Closed
wants to merge 4 commits into from
Closed
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
134 changes: 89 additions & 45 deletions scdl/scdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,55 @@
"""scdl allows you to download music from Soundcloud

Usage:
scdl -l <track_url> [-a | -f | -C | -t | -p][-c][-n <maxtracks>][-o <offset>]\
[--hidewarnings][--debug | --error][--path <path>][--addtofile][--addtimestamp]
[--onlymp3][--hide-progress][--min-size <size>][--max-size <size>][--remove]
[--no-playlist-folder][--download-archive <file>][--extract-artist][--flac]
scdl me (-s | -a | -f | -t | -p | -m)[-c][-o <offset>]\
[--hidewarnings][--debug | --error][--path <path>][--addtofile][--addtimestamp]
[--onlymp3][--hide-progress][--min-size <size>][--max-size <size>][--remove]
[--no-playlist-folder][--download-archive <file>][--extract-artist][--flac]
scdl (-l <track_url> | -q <search_query>) [options]
scdl me (-s | -a | -f | -t | -p | -m) [options]
scdl -h | --help
scdl --version


Options:
-h --help Show this screen
--version Show version
me Use the user profile from the auth_token
-l [url] URL can be track/playlist/user
-n [maxtracks] Download the n last tracks of a playlist according to the creation date
-s Download the stream of a user (token needed)
-a Download all tracks of user (including reposts)
-t Download all uploads of a user (no reposts)
-f Download all favorites of a user
-C Download all commented by a user
-p Download all playlists of a user
-m Download all liked and owned playlists of user
-c Continue if a downloaded file already exists
-o [offset] Begin with a custom offset
--addtimestamp Add track creation timestamp to filename,
which allows for chronological sorting
--addtofile Add artist to filename if missing
--debug Set log level to DEBUG
--download-archive [file] Keep track of track IDs in an archive file,
and skip already-downloaded files
--error Set log level to ERROR
--extract-artist Set artist tag from title instead of username
--hide-progress Hide the wget progress bar
--hidewarnings Hide Warnings. (use with precaution)
--max-size [max-size] Skip tracks larger than size (k/m/g)
--min-size [min-size] Skip tracks smaller than size (k/m/g)
--no-playlist-folder Download playlist tracks into main directory,
instead of making a playlist subfolder
--onlymp3 Download only the streamable mp3 file,
even if track has a Downloadable file
--path [path] Use a custom path for downloaded files
--remove Remove any files not downloaded from execution
--flac Convert original files to .flac
-h --help Show this screen
--version Show version
-l <track_url> URL can be track/playlist/user
-q <search_query> Search for a track/playlist/user and use the first result
-s Download the stream of a user
-a Download all tracks of user (including reposts)
-t Download all uploads of a user (no reposts)
-f Download all favorites of a user
-C Download all commented by a user
-p Download all playlists of a user
-m Download all likes and owned playlists of user
-c Continue if a downloaded file already exists
-n <maxtracks> Download the n last tracks of a playlist [default: all]
-o <offset> Begin with a custom offset
--addtimestamp Add track creation timestamp to filename
--addtofile Add artist to filename if missing
--debug Set log level to DEBUG
--download-archive <file> Keep track of track IDs in an archive file, and skip already-downloaded files
--error Set log level to ERROR
--extract-artist Set artist tag from title instead of username
--hide-progress Hide the wget progress bar
--hidewarnings Hide Warnings (use with precaution)
--max-size <size> Skip tracks larger than size (k/m/g)
--min-size <size> Skip tracks smaller than size (k/m/g)
--no-playlist-folder Download playlist tracks into main directory
--onlymp3 Download only the streamable mp3 file
--path <path> Use a custom path for downloaded files
--remove Remove any files not downloaded from execution
--flac Convert original files to .flac
--original-art Download original cover art
--original-name Do not change name of original file downloads
--original-metadata Do not change metadata of original file downloads
--no-original Do not download original file
--only-original Only download songs with original file available
--name-format <format> Specify the downloaded file name format
--playlist-name-format <format> Specify the playlist name format
--client-id <id> Specify the client_id to use
--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
--add-description Adds the description to a separate txt file
--no-playlist Skip downloading playlists
--opus Prefer downloading opus streams over mp3 streams
"""

import logging
Expand Down Expand Up @@ -104,7 +107,8 @@
'trackinfo': ('https://api-v2.soundcloud.com/tracks/{0}'),
'original_download' : ("https://api-v2.soundcloud.com/tracks/{0}/download"),
'user': ('https://api-v2.soundcloud.com/users/{0}'),
'me': ('https://api-v2.soundcloud.com/me?oauth_token={0}')
'me': ('https://api-v2.soundcloud.com/me?oauth_token={0}'),
'search': ('https://api-v2.soundcloud.com/search/queries?q={0}&limit=1&offset=0')
}
client = client.Client()

Expand Down Expand Up @@ -180,6 +184,16 @@ def main():

if arguments['-l']:
parse_url(arguments['-l'])
elif arguments['-q']:
search_query = arguments['-q']
url = search_soundcloud(search_query)
if url:
logger.info(url)
parse_url(url)
else:
logger.error("Search failed. Exiting...")
sys.exit(1)

elif arguments['me']:
if arguments['-f']:
download(who_am_i(), 'favorites', 'likes')
Expand All @@ -197,6 +211,36 @@ def main():
if arguments['--remove']:
remove_files()

def search_soundcloud(query: str, client_id=CLIENT_ID):
"""
Search SoundCloud and return the URL of the first result
"""
try:
search_url = url['search'].format(query)
r = requests.get(search_url, params={'client_id': client_id})
logger.debug(r.url)
logger.debug(r.status_code)
if r.status_code == 403:
return search_soundcloud(query, ALT_CLIENT_ID)

results = r.json()
logger.debug(results)
if results['collection']:
item = results['collection'][0]
if item['kind'] in ['track', 'playlist', 'user']:
return item['permalink_url']
logger.warning(f"Unexpected search result type: {item['kind']}")
logger.error(f"No results found for query: {query}")
except Exception as e:
if client_id == ALT_CLIENT_ID:
logger.error('Failed to search...')
return None
logger.error(e)
logger.error('Error searching, retrying...')
time.sleep(5)
return search_soundcloud(query, ALT_CLIENT_ID)
return None


def get_config():
"""
Expand Down Expand Up @@ -451,7 +495,7 @@ def download_original_file(track, title):
if r.status_code == 401:
logger.info('The original file has no download left.')
return None

if r.status_code == 404:
logger.info('Could not get name from stream - using basic name')
return None
Expand Down Expand Up @@ -491,7 +535,7 @@ def download_original_file(track, title):
newfilename = filename[:-4] + ".flac"
new = shlex.quote(newfilename)
old = shlex.quote(filename)

commands = ['ffmpeg', '-i', old, new, '-loglevel', 'fatal']
logger.debug("Commands: {}".format(commands))
subprocess.call(commands)
Expand Down