diff --git a/README.md b/README.md index e6daaca..af0a336 100755 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ That's how your Music library will look like! ## Reporting Issues -- Search for your problem in the [issues section](https://github.com/Ritiek/spotify-downloader/issues?utf8=%E2%9C%93&q=) before opening a new ticket. It might be already answered and save us time :smile:. +- Search for your problem in the [issues section](https://github.com/Ritiek/spotify-downloader/issues?utf8=%E2%9C%93&q=) before opening a new ticket. It might be already answered and save us time. :smile: - Provide as much information possible when opening your ticket. @@ -73,8 +73,8 @@ Assuming you have Python already installed.. - For all available options, run `python spotdl.py --help` (or for Windows run `python.exe spotdl.py --help`). ``` -usage: spotdl.py [-h] (-s SONG | -l LIST | -u USERNAME) [-n] [-m] [-f] [-v] - [-i INPUT_EXT] [-o OUTPUT_EXT] +usage: spotdl.py [-h] (-s SONG | -l LIST | -p PLAYLIST | -u USERNAME) [-m] + [-nm] [-a] [-f FOLDER] [-v] [-i INPUT_EXT] [-o OUTPUT_EXT] Download and convert songs from Spotify, Youtube etc. @@ -82,12 +82,16 @@ optional arguments: -h, --help show this help message and exit -s SONG, --song SONG download song by spotify link or name (default: None) -l LIST, --list LIST download songs from a file (default: None) - -u USERNAME, --username USERNAME - load user's playlists into .txt + -p PLAYLIST, --playlist PLAYLIST + load songs from playlist URL into .txt (default: None) + -u USERNAME, --username USERNAME + load songs from user's playlist into + .txt (default: None) -m, --manual choose the song to download manually (default: False) - -a, --avconv Use avconv for conversion. If not set - defaults to FFmpeg (default: False) + -nm, --no-metadata do not embed metadata in songs (default: False) + -a, --avconv Use avconv for conversion otherwise set defaults to + ffmpeg (default: False) -f FOLDER, --folder FOLDER path to folder where files will be stored in (default: Music/) @@ -100,7 +104,7 @@ optional arguments: .mp3) ``` -#### Downloading by Name +#### Download by Name For example @@ -110,7 +114,7 @@ For example - It will now convert the song to an mp3 and try to fix meta-tags and album-art by looking up on Spotify. -#### Downloading by Spotify Link (Recommended) +#### Download by Spotify Link (Recommended) For example @@ -146,15 +150,27 @@ http://open.spotify.com/track/64yrDBpcdwEdNY9loyEGbX - Songs that are already downloaded will be skipped and not be downloaded again. -#### Downloading playlists +#### Download playlists -- You can also load songs from any playlist provided you have a Spotify username or user id of that user. (Open profile in Spotify, click on the three little dots below name, "Share", "Copy to clipboard", paste last numbers into command-line: `https://open.spotify.com/user/0123456790`) +- You can copy the Spotify URL of the playlist and pass it in `--playlist` option. + +For example + +- `python spodl.py --playlist https://open.spotify.com/user/camillazi/playlist/71MXqcSOKCxsLNtRvONkhF` + +- The script will load all the tracks from the playlist into `.txt` + +- Then you can simply run `python spotdl.py --list=.txt` to download all the tracks. + +#### Download playlists by username + +- You can also load songs using Spotify username if you don't have the playlist URL. (Open profile in Spotify, click on the three little dots below name, "Share", "Copy to clipboard", paste last numbers into command-line: `https://open.spotify.com/user/0123456790`) - Try running `python spotdl.py -u `, it will show all your public playlists. -- Once you select the one you want to download, the script will load all the tracks from the playlist into `.txt` +- Once you select the one you want to download, the script will load all the tracks from the playlist into `.txt`. -- Then you can simply run `python spotdl.py --list=.txt` to download them all! +- Run `python spotdl.py --list=.txt` to download all the tracks. #### Specify the target directory @@ -162,7 +178,9 @@ If you don't want to download all the songs to the `Music/` folder relative to t ## Running tests -`python -m pytest test` +``` +python -m pytest test +``` Obviously this requires the `pytest` module to be installed. diff --git a/core/misc.py b/core/misc.py index 5f84261..9d33063 100755 --- a/core/misc.py +++ b/core/misc.py @@ -39,9 +39,11 @@ def get_arguments(): '-s', '--song', help='download song by spotify link or name') group.add_argument( '-l', '--list', help='download songs from a file') + group.add_argument( + '-p', '--playlist', help='load songs from playlist URL into .txt') group.add_argument( '-u', '--username', - help="load user's playlists into .txt") + help="load songs from user's playlist into .txt") parser.add_argument( '-m', '--manual', default=False, help='choose the song to download manually', action='store_true') diff --git a/spotdl.py b/spotdl.py index f036a97..08576fe 100755 --- a/spotdl.py +++ b/spotdl.py @@ -51,9 +51,7 @@ def generate_metadata(raw_song): meta_tags[u'release_date'] = album['release_date'] meta_tags[u'publisher'] = album['label'] meta_tags[u'total_tracks'] = album['tracks']['total'] - # import pprint - # pprint.pprint(meta_tags) - # pprint.pprint(spotify.album(meta_tags['album']['id'])) + return meta_tags @@ -128,7 +126,7 @@ def feed_playlist(username): # in rare cases, playlists may not be found, so playlists['next'] # is None. Skip these. Also see Issue #91. if playlist['name'] is not None: - print(u'{0:>5}.| {1:<30} | ({2} tracks)'.format( + print(u'{0:>5}. {1:<30} ({2} tracks)'.format( check, playlist['name'], playlist['tracks']['total'])) links.append(playlist) @@ -140,9 +138,13 @@ def feed_playlist(username): print('') playlist = misc.input_link(links) + print('') + write_tracks(playlist) + + +def write_tracks(playlist): results = spotify.user_playlist( playlist['owner']['id'], playlist['id'], fields='tracks,next') - print('') text_file = u'{0}.txt'.format(slugify(playlist['name'], ok='-_()[]{}')) print(u'Feeding {0} tracks to {1}'.format(playlist['tracks']['total'], text_file)) @@ -163,6 +165,7 @@ def feed_playlist(username): else: break + def download_song(file_name, content): """Download the audio file from YouTube.""" if args.input_ext == '.webm': @@ -255,6 +258,32 @@ def grab_list(text_file): number += 1 +def grab_playlist(playlist): + if '/' in playlist: + if playlist.endswith('/'): + playlist = playlist[:-1] + splits = playlist.split('/') + else: + splits = playlist.split(':') + + username = splits[-3] + playlist_id = splits[-1] + playlists = spotify.user_playlists(username) + + while True: + for playlist in playlists['items']: + if not playlist['name'] == None: + if playlist['id'] == playlist_id: + playlists['next'] = None + break + if playlists['next']: + playlists = spotify.next(playlists) + else: + break + + write_tracks(playlist) + + def grab_single(raw_song, number=None): """Logic behind downloading a song.""" if number: @@ -290,13 +319,12 @@ def grab_single(raw_song, number=None): print('No audio streams available') -class Args(object): +class TestArgs(object): manual = False input_ext = '.m4a' output_ext = '.mp3' folder = 'Music/' -args = Args() # token is mandatory when using Spotify's API # https://developer.spotify.com/news-stories/2017/01/27/removing-unauthenticated-calls-to-the-web-api/ token = misc.generate_token() @@ -312,8 +340,10 @@ if __name__ == '__main__': grab_single(raw_song=args.song) elif args.list: grab_list(text_file=args.list) + elif args.playlist: + grab_playlist(playlist=args.playlist) elif args.username: feed_playlist(username=args.username) else: misc.filter_path('Music') - + args = TestArgs()