def test_spotify_playlist_fetch_more(): sp = spotify_auth() url = "https://open.spotify.com/playlist/3cEYpjA9oz9GiPac4AsH4n" item_type = "playlist" songs = fetch_tracks(sp, item_type, url) assert [{'album': 'Progressive Psy Trance Picks Vol.8', 'artist': 'Odiseo', 'cover': 'https://i.scdn.co/image/ab67616d0000b273ce6d0eef0c1ce77e5f95bbbc', 'genre': 'progressive psytrance', 'name': 'Api', 'num': 10, 'num_tracks': 20, 'year': '2012', 'playlist_num': 1, 'spotify_id': '4rzfv0JLZfVhOhbSQ8o5jZ'}, {'album': 'Wellness & Dreaming Source', 'artist': 'Vlasta Marek', 'cover': 'https://i.scdn.co/image/ab67616d0000b273aa2ff29970d9a63a49dfaeb2', 'genre': 'singing bowl', 'name': 'Is', 'num': 21, 'num_tracks': 25, 'year': '2015', 'playlist_num': 2, 'spotify_id': '5o3jMYOSbaVz3tkgwhELSV'}, {'album': 'This Is Happening', 'artist': 'LCD Soundsystem', 'cover': 'https://i.scdn.co/image/ab67616d0000b273ee0d0dce888c6c8a70db6e8b', 'genre': 'alternative dance', 'name': 'All I Want', 'num': 4, 'num_tracks': 9, 'year': '2010', 'playlist_num': 3, 'spotify_id': '4Cy0NHJ8Gh0xMdwyM9RkQm'}, {'album': 'Glenn Horiuchi Trio / Gelenn Horiuchi Quartet: Mercy / Jump Start ' '/ Endpoints / Curl Out / Earthworks / Mind Probe / Null Set / ' 'Another Space (A)', 'artist': 'Glenn Horiuchi Trio', 'cover': 'https://i.scdn.co/image/ab67616d0000b2738b7447ac3daa1da18811cf7b', 'genre': '', 'name': 'Endpoints', 'num': 2, 'num_tracks': 8, 'year': '2011', 'playlist_num': 4, 'spotify_id': '6hvFrZNocdt2FcKGCSY5NI'}, {'album': 'All The Best (Spanish Version)', 'artist': 'Zucchero', 'cover': 'https://i.scdn.co/image/ab67616d0000b27304e57d181ff062f8339d6c71', 'genre': 'classic italian pop', 'name': 'You Are So Beautiful', 'num': 18, 'num_tracks': 18, 'year': '2007', 'playlist_num': 5, 'spotify_id': '2E2znCPaS8anQe21GLxcvJ'}] == songs
def test_spotify_playlist_fetch_local_file(): sp = spotify_auth() url = "https://open.spotify.com/playlist/1TWZ36xJ8qkvSeAQQUvU5b?si=ad56b6bb085b4ab9" item_type = "playlist" songs = fetch_tracks(sp, item_type, url) assert [{'album': "Yoshi's Island", 'artist': 'Koji Kondo', 'cover': None, 'genre': '', 'name': 'Flower Garden', 'num': 0, 'num_tracks': None, 'year': '', 'playlist_num': 1, 'spotify_id': None}] == songs
def test_spotify_playlist_fetch_one(): sp = spotify_auth() url = "https://open.spotify.com/playlist/1EqaIF6DswCUE0I6gAzQQv?si=9BzJyGNRSGOZ-nsL66WmmA" item_type = "playlist" songs = fetch_tracks(sp, item_type, url) assert {'album': 'Hell Freezes Over (Remaster 2018)', 'artist': 'Eagles', 'cover': 'https://i.scdn.co/image/ab67616d0000b27396d28597a5ae44ab66552183', 'genre': 'album rock', 'name': 'Hotel California - Live On MTV, 1994', 'num': 6, 'num_tracks': 15, 'year': '1994', 'playlist_num': 1, 'spotify_id': '2GpBrAoCwt48fxjgjlzMd4'} == songs[0]
def download_spotify(sp, args): if args.output: item_type, item_id = parse_spotify_url(args.url) directory_name = get_item_name(sp, item_type, item_id) save_path = Path(args.output) if args.createdir: save_path = Path( PurePath.joinpath(Path(args.output), Path(directory_name))) save_path.mkdir(parents=True, exist_ok=True) log.info("Saving songs to: {}".format(directory_name)) songs = fetch_tracks(sp, item_type, args.url) if args.download is True: download_songs(songs, save_path, args.format_str, args.skip_mp3, args.keep_playlist_order)
def test_spotify_track_fetch_one(): sp = spotify_auth() url = "https://open.spotify.com/track/2GpBrAoCwt48fxjgjlzMd4?si=xzZIHC5hSGuSEAXXkxgKiw" item_type = "track" songs = fetch_tracks(sp, item_type, url) assert {'album': 'Hell Freezes Over (Remaster 2018)', 'artist': 'Eagles', 'cover': 'https://i.scdn.co/image/ab67616d0000b27396d28597a5ae44ab66552183', 'genre': 'album rock', 'name': 'Hotel California - Live On MTV, 1994', 'num': 6, 'num_tracks': 15, 'year': '1994', 'playlist_num': 1, 'spotify_id': '2GpBrAoCwt48fxjgjlzMd4'} == songs[0]
def test_spotify_album_fetch_one(): sp = spotify_auth() url = "https://open.spotify.com/album/1IVEQdX6Y37za9PMB0afPX?si=Hz8CMaYpTx2O0PeuDglKaA" item_type = "album" songs = fetch_tracks(sp, item_type, url) assert {'album': 'Simple Song', 'artist': 'The Shins', 'cover': 'https://i.scdn.co/image/ab67616d0000b2737f6f8d24f3bba324727d6021', 'genre': 'albuquerque indie', 'name': 'Simple Song', 'num': 1, 'num_tracks': 1, 'year': '2012', 'playlist_num': 1, 'spotify_id': '5EoKQDGE2zxrTfRFZF52u5'} == songs[0]
def get_songs(self, url): valid_item = validate_spotify_url(url) item_type, item_id = spotify.parse_spotify_url(url) directory_name = spotify.get_item_name( self.sp, item_type, item_id).replace("ä", "ae").replace( "ö", "oe").replace("ü", "ue").replace("ß", "ss") save_path = Path( PurePath.joinpath(Path(self.result_dir), Path(directory_name))) save_path.mkdir(parents=True, exist_ok=True) self.dl_path = str(save_path) print("[LOG] Saving Songs to " + self.dl_path) self.debug.append("[LOG] Saving Songs to " + self.dl_path) songs = spotify.fetch_tracks(self.sp, item_type, url) return songs
def update_files(self): """Check if files in the job directory match the contents of the playlist. Delete or download old/new files. """ log.info('Updating files ...') (_, _, filenames) = next(os.walk(self.directory)) filenames = [f for f in filenames if f.endswith('.mp3')] newtracks = list(self.tracks.keys()) for f in filenames: name, extension = os.path.splitext(f) if f.endswith('.json'): continue elif name in newtracks: # track already downloaded newtracks.remove(name) # newtracks.remove(name) elif name not in newtracks: # track downloaded but no longer needed log.info(f'Deleting file {name} since no longer in playlist.') os.remove(os.path.join(self.directory, name + extension)) log.info(f'Checked files for {self.PLname}: {len(newtracks)}' ' new tracks to download.') for uri in newtracks: data = self.tracks[uri] songs = fetch_tracks(self.sp_client, 'track', data['external_urls']['spotify']) download_songs(songs, self.directory, 'bestaudio/best', False) # Filename convention for spotify_dl.youtube (this could break) # --> f"{song.get('artist')} - {song.get('name')}.mp3" # Rename file to {uri}.mp3 (that's how this script operates) os.rename( os.path.join( self.directory, f"{songs[0].get('artist')} - {songs[0].get('name')}.mp3"), os.path.join(self.directory, f"{uri}.mp3")) log.info(f'Downloaded track {data["name"]} ({uri}).') log.info('Finished updating files ...')
def spotify_dl(): parser = argparse.ArgumentParser(prog='spotify_dl') parser.add_argument('-d', '--download', action='store_true', help='Download using youtube-dl') parser.add_argument('-p', '--playlist', action='store', help='Download from playlist id instead of saved tracks') parser.add_argument('-V', '--verbose', action='store_true', help='Show more information on what''s happening.') parser.add_argument('-o', '--output', type=str, action='store', nargs='*', help='Specify download directory.') parser.add_argument('-u', '--user_id', action='store', help='Specify the playlist owner\'s userid when it is different than your spotify userid') args = parser.parse_args() if args.verbose: log.setLevel(DEBUG) log.info('Starting spotify_dl') log.debug('setting debug mode on spotify_dl') if not check_for_tokens(): exit() token = authenticate() if args.output: download_directory = args.output[0] # Check whether directory has a trailing slash or not if len(download_directory) >= 0 and download_directory[-1] != '/': download_directory += '/' else: download_directory = '' sp = spotipy.Spotify(auth=token) songs = fetch_tracks(sp, args.playlist, args.user_id) url = [] for s in songs: link = fetch_youtube_url(s) if link: url.append(link) save_songs_to_file(url) if args.download is True: download_songs(url, download_directory)
def spotify_dl(): parser = argparse.ArgumentParser(prog='spotify_dl') parser.add_argument('-d', '--download', action='store_true', help='Download using youtube-dl', default=True) parser.add_argument('-p', '--playlist', action='store', help='Download from playlist id instead of' ' saved tracks') parser.add_argument('-V', '--verbose', action='store_true', help='Show more information on what' 's happening.') parser.add_argument('-o', '--output', type=str, action='store', nargs='*', help='Specify download directory.') parser.add_argument('-u', '--user_id', action='store', help='Specify the playlist owner\'s userid when it' ' is different than your spotify userid') parser.add_argument('-i', '--uri', type=str, action='store', nargs='*', help='Given a URI, download it.') args = parser.parse_args() if args.verbose: log.setLevel(DEBUG) log.info('Starting spotify_dl') log.debug('setting debug mode on spotify_dl') if not check_for_tokens(): exit() token = authenticate() sp = spotipy.Spotify(auth=token) if args.uri: current_user_id, playlist_id = extract_user_and_playlist_from_uri( args.uri[0]) else: if args.user_id is None: current_user_id = sp.current_user()['id'] else: current_user_id = args.user_id if args.output: if args.uri: uri = args.uri[0] playlist = playlist_name(uri, sp) else: playlist = get_playlist_name_from_id(args.playlist, current_user_id, sp) log.info("Saving songs to: {}".format(playlist)) download_directory = args.output[0] + '/' + playlist # Check whether directory has a trailing slash or not if len(download_directory) >= 0 and download_directory[-1] != '/': download_directory += '/' if not os.path.exists(download_directory): os.makedirs(download_directory) else: download_directory = '' if args.uri: songs = fetch_tracks(sp, playlist_id, current_user_id) else: songs = fetch_tracks(sp, args.playlist, current_user_id) url = [] for song, artist in songs.items(): link = fetch_youtube_url(song + ' - ' + artist) if link: url.append((link, song, artist)) save_songs_to_file(url, download_directory) if args.download is True: download_songs(url, download_directory)
def test_spotify_album_fetch_more(): sp = spotify_auth() url = "https://open.spotify.com/album/2RKEso6nin3nhRyAd36Omv?si=KEBaFQxYR9-nRJLarH2QNQ" item_type = "album" songs = fetch_tracks(sp, item_type, url) assert [{ 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Procession - Remastered 2011', 'num': 1, 'num_tracks': 16, 'year': '1974', 'playlist_num': 1, 'spotify_id': '69Yw7H4bRIwfIxL0ZCZy8y' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Father To Son - Remastered 2011', 'num': 2, 'num_tracks': 16, 'year': '1974', 'playlist_num': 2, 'spotify_id': '5GGSjXZeTgX9sKYBtl8K6U' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'White Queen (As It Began) - Remastered 2011', 'num': 3, 'num_tracks': 16, 'year': '1974', 'playlist_num': 3, 'spotify_id': '0Ssh20fuVhmasLRJ97MLnp' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Some Day One Day - Remastered 2011', 'num': 4, 'num_tracks': 16, 'year': '1974', 'playlist_num': 4, 'spotify_id': '2LasW39KJDE4VH9hTVNpE2' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'The Loser In The End - Remastered 2011', 'num': 5, 'num_tracks': 16, 'year': '1974', 'playlist_num': 5, 'spotify_id': '6jXrIu3hWbmJziw34IHIwM' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Ogre Battle - Remastered 2011', 'num': 6, 'num_tracks': 16, 'year': '1974', 'playlist_num': 6, 'spotify_id': '5dHmGuUeRgp5f93G69tox5' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': "The Fairy Feller's Master-Stroke - Remastered 2011", 'num': 7, 'num_tracks': 16, 'year': '1974', 'playlist_num': 7, 'spotify_id': '2KPj0oB7cUuHQ3FuardOII' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Nevermore - Remastered 2011', 'num': 8, 'num_tracks': 16, 'year': '1974', 'playlist_num': 8, 'spotify_id': '34CcBjL9WqEAtnl2i6Hbxa' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'The March Of The Black Queen - Remastered 2011', 'num': 9, 'num_tracks': 16, 'year': '1974', 'playlist_num': 9, 'spotify_id': '1x9ak6LGIazLhfuaSIEkhG' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Funny How Love Is - Remastered 2011', 'num': 10, 'num_tracks': 16, 'year': '1974', 'playlist_num': 10, 'spotify_id': '4CITL18Tos0PscW1amCK4j' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Seven Seas Of Rhye - Remastered 2011', 'num': 11, 'num_tracks': 16, 'year': '1974', 'playlist_num': 11, 'spotify_id': '1e9Tt3nKBwRbuaU79kN3dn' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': "See What A Fool I've Been - Live BBC Session, London / July 1973 / " '2011 Remix', 'num': 1, 'num_tracks': 16, 'year': '1974', 'playlist_num': 12, 'spotify_id': '0uHqoDT7J2TYBsJx6m4Tvi' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'White Queen (As It Began) - Live At Hammersmith Odeon, London / ' 'December 1975', 'num': 2, 'num_tracks': 16, 'year': '1974', 'playlist_num': 13, 'spotify_id': '3MIueGYoNiyBNfi5ukDgAK' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Seven Seas Of Rhye - Instrumental Mix 2011', 'num': 3, 'num_tracks': 16, 'year': '1974', 'playlist_num': 14, 'spotify_id': '34WAOFWdJ83a3YYrDAZTjm' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Nevermore - Live BBC Session, London / April 1974', 'num': 4, 'num_tracks': 16, 'year': '1974', 'playlist_num': 15, 'spotify_id': '2AFIPUlApcUwGEgOSDwoBz' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'See What A Fool I’ve Been - B-Side Version / Remastered 2011', 'num': 5, 'num_tracks': 16, 'year': '1974', 'playlist_num': 16, 'spotify_id': '4G4Sf18XkFvNTV5vAxiQyd' }] == songs assert (len(songs)) == 16
def spotify_dl(): """Main entry point of the script.""" parser = argparse.ArgumentParser(prog='spotify_dl') parser.add_argument('-l', '--url', action="store", help="Spotify Playlist link URL", type=str, required=True) parser.add_argument('-o', '--output', type=str, action='store', help='Specify download directory.', required=True) parser.add_argument('-d', '--download', action='store_true', help='Download using youtube-dl', default=True) parser.add_argument('-f', '--format_str', type=str, action='store', help='Specify youtube-dl format string.', default='bestaudio/best') parser.add_argument( '-k', '--keep_playlist_order', default=False, action='store_true', help='Whether to keep original playlist ordering or not.') parser.add_argument('-m', '--skip_mp3', action='store_true', help='Don\'t convert downloaded songs to mp3') parser.add_argument('-s', '--scrape', action="store", help="Use HTML Scraper for YouTube Search", default=True) parser.add_argument('-V', '--verbose', action='store_true', help='Show more information on what' 's happening.') parser.add_argument('-v', '--version', action='store_true', help='Shows current version of the program') args = parser.parse_args() if args.version: print("spotify_dl v{}".format(VERSION)) exit(0) db.connect() db.create_tables([Song]) if os.path.isfile(os.path.expanduser('~/.spotify_dl_settings')): with open(os.path.expanduser('~/.spotify_dl_settings')) as file: config = json.loads(file.read()) for key, value in config.items(): if value and (value.lower() == 'true' or value.lower() == 't'): setattr(args, key, True) else: setattr(args, key, value) if args.verbose: log.setLevel(DEBUG) log.info('Starting spotify_dl') log.debug('Setting debug mode on spotify_dl') if not check_for_tokens(): exit(1) sp = spotipy.Spotify(auth_manager=SpotifyClientCredentials()) log.debug('Arguments: {}'.format(args)) if args.url: valid_item = validate_spotify_url(args.url) if not valid_item: sys.exit(1) if args.output: item_type, item_id = parse_spotify_url(args.url) directory_name = get_item_name(sp, item_type, item_id) save_path = Path( PurePath.joinpath(Path(args.output), Path(directory_name))) save_path.mkdir(parents=True, exist_ok=True) log.info("Saving songs to: {}".format(directory_name)) songs = fetch_tracks(sp, item_type, args.url) if args.download is True: file_name_f = default_filename if args.keep_playlist_order: file_name_f = playlist_num_filename download_songs(songs, save_path, args.format_str, args.skip_mp3, args.keep_playlist_order, file_name_f)
def test_spotify_track_fetch(): sp = spotify_auth() url = "https://open.spotify.com/track/2GpBrAoCwt48fxjgjlzMd4?si=xzZIHC5hSGuSEAXXkxgKiw" item_type = "track" songs = fetch_tracks(sp, item_type, url) assert {'Hotel California - Live On MTV, 1994': 'Eagles'} == songs
def spotify_dl(): """Main entry point of the script.""" parser = argparse.ArgumentParser(prog='spotify_dl') parser.add_argument('-d', '--download', action='store_true', help='Download using youtube-dl', default=True) parser.add_argument('-p', '--playlist', action='store', help='Download from playlist id instead of' ' saved tracks') parser.add_argument('-V', '--verbose', action='store_true', help='Show more information on what' 's happening.') parser.add_argument('-v', '--version', action='store_true', help='Shows current version of the program') parser.add_argument('-o', '--output', type=str, action='store', help='Specify download directory.') parser.add_argument('-u', '--user_id', action='store', help='Specify the playlist owner\'s userid when it' ' is different than your spotify userid') parser.add_argument('-i', '--uri', type=str, action='store', nargs='*', help='Given a URI, download it.') parser.add_argument('-f', '--format_str', type=str, action='store', help='Specify youtube-dl format string.', default='bestaudio/best') parser.add_argument('-m', '--skip_mp3', action='store_true', help='Don\'t convert downloaded songs to mp3') parser.add_argument('-l', '--url', action="store", help="Spotify Playlist link URL") parser.add_argument('-s', '--scrape', action="store", help="Use HTML Scraper for YouTube Search", default=True) args = parser.parse_args() playlist_url_pattern = re.compile(r'^https://open.spotify.com/(.+)$') if args.version: print("spotify_dl v{}".format(VERSION)) exit(0) db.connect() db.create_tables([Song]) if os.path.isfile(os.path.expanduser('~/.spotify_dl_settings')): with open(os.path.expanduser('~/.spotify_dl_settings')) as file: config = json.loads(file.read()) for key, value in config.items(): if value and (value.lower() == 'true' or value.lower() == 't'): setattr(args, key, True) else: setattr(args, key, value) if args.verbose: log.setLevel(DEBUG) log.info('Starting spotify_dl') log.debug('Setting debug mode on spotify_dl') if not check_for_tokens(): exit(1) token = authenticate() sp = spotipy.Spotify(auth=token) log.debug('Arguments: {}'.format(args)) if args.url: url_match = playlist_url_pattern.match(args.url) if url_match and len(url_match.groups()) > 0: uri = "spotify:" + url_match.groups()[0].replace('/', ':') args.uri = [uri] else: raise Exception('Invalid playlist URL ') if args.uri: current_user_id, playlist_id = extract_user_and_playlist_from_uri( args.uri[0], sp) else: if args.user_id is None: current_user_id = sp.current_user()['id'] else: current_user_id = args.user_id if args.output: if args.uri: uri = args.uri[0] playlist = playlist_name(uri, sp) else: playlist = get_playlist_name_from_id(args.playlist, current_user_id, sp) log.info("Saving songs to: {}".format(playlist)) download_directory = args.output + '/' + playlist if len(download_directory) >= 0 and download_directory[-1] != '/': download_directory += '/' if not os.path.exists(download_directory): os.makedirs(download_directory) else: download_directory = '' if args.uri: songs = fetch_tracks(sp, playlist_id, current_user_id) else: songs = fetch_tracks(sp, args.playlist, current_user_id) url = [] for song, artist in songs.items(): link = fetch_youtube_url(song + ' - ' + artist, get_youtube_dev_key()) if link: url.append((link, song, artist)) save_songs_to_file(url, download_directory) if args.download is True: download_songs(url, download_directory, args.format_str, args.skip_mp3)
def spotify_dl(): parser = argparse.ArgumentParser(prog='spotify_dl') parser.add_argument('-d', '--download', action='store_true', help='Download using youtube-dl') parser.add_argument('-p', '--playlist', action='store', help='Download from playlist id instead of' ' saved tracks') parser.add_argument('-V', '--verbose', action='store_true', help='Show more information on what''s happening.') parser.add_argument('-o', '--output', type=str, action='store', nargs='*', help='Specify download directory.') parser.add_argument('-u', '--user_id', action='store', help='Specify the playlist owner\'s userid when it' ' is different than your spotify userid') parser.add_argument('-s', '--save', action='store_true', help='Create on Desktop a folder named' 'with the Playlist Name') parser.add_argument('-i', '--uri', type=str, action='store', nargs='*', help='Given a URI, download it.') args = parser.parse_args() if args.verbose: log.setLevel(DEBUG) log.info('Starting spotify_dl') log.debug('setting debug mode on spotify_dl') if not check_for_tokens(): exit() token = authenticate() sp = spotipy.Spotify(auth=token) if args.output: download_directory = args.output[0] # Check whether directory has a trailing slash or not if len(download_directory) >= 0 and download_directory[-1] != '/': download_directory += '/' elif args.save is True: uri = args.uri[0] playlist = playlist_name(uri, sp) download_directory = os.path.expanduser('~/Desktop') + '/' + playlist if len(download_directory) >= 0 and download_directory[-1] != '/': download_directory += '/' if not os.path.exists(download_directory): os.makedirs(download_directory) else: download_directory = '' if args.uri: user_id, playlist_id = extract_user_and_playlist_from_uri(args.uri[0]) songs = fetch_tracks(sp, playlist_id, user_id) else: songs = fetch_tracks(sp, args.playlist, args.user_id) url = [] for song, artist in songs.items(): link = fetch_youtube_url(song + ' - ' + artist) if link: url.append((link, song, artist)) save_songs_to_file(url, download_directory) if args.download is True: download_songs(url, download_directory)
def spotify_dl(): parser = argparse.ArgumentParser(prog='spotify_dl') parser.add_argument('-d', '--download', action='store_true', help='Download using youtube-dl', default=True) parser.add_argument('-p', '--playlist', action='store', help='Download from playlist id instead of' ' saved tracks') parser.add_argument('-V', '--verbose', action='store_true', help='Show more information on what' 's happening.') parser.add_argument('-v', '--version', action='store_true', help='Shows current version of the program') parser.add_argument('-o', '--output', type=str, action='store', nargs='*', help='Specify download directory.') parser.add_argument('-u', '--user_id', action='store', help='Specify the playlist owner\'s userid when it' ' is different than your spotify userid') parser.add_argument('-i', '--uri', type=str, action='store', nargs='*', help='Given a URI, download it.') parser.add_argument('-f', '--format_str', type=str, action='store', nargs='*', help='Specify youtube-dl format string.', default=['bestaudio/best']) parser.add_argument('-m', '--skip_mp3', action='store_true', help='Don\'t convert downloaded songs to mp3') parser.add_argument('-l', '--url', action="store", help="Spotify Playlist link URL") args = parser.parse_args() if args.version: print("spotify_dl v{}".format(VERSION)) exit(0) if os.path.isfile(os.path.expanduser('~/.spotify_dl_settings')): with open(os.path.expanduser('~/.spotify_dl_settings')) as file: config = json.loads(file.read()) for key, value in config.items(): if value and (value.lower() == 'true' or value.lower() == 't'): setattr(args, key, True) else: setattr(args, key, value) if args.verbose: log.setLevel(DEBUG) log.info('Starting spotify_dl') log.debug('Setting debug mode on spotify_dl') if not check_for_tokens(): exit(1) token = authenticate() sp = spotipy.Spotify(auth=token) log.debug('Arguments: {}'.format(args)) if args.url is not None: url = args.url.split("open.spotify.com/")[1].split("/") uri = ":".join(url) uri = "spotify:" + uri args.uri = [] args.uri.append(uri) if args.uri: current_user_id, playlist_id = extract_user_and_playlist_from_uri( args.uri[0]) else: if args.user_id is None: current_user_id = sp.current_user()['id'] else: current_user_id = args.user_id if args.output: if args.uri: uri = args.uri[0] playlist = playlist_name(uri, sp) else: playlist = get_playlist_name_from_id(args.playlist, current_user_id, sp) log.info("Saving songs to: {}".format(playlist)) download_directory = args.output + '/' + playlist # Check whether directory has a trailing slash or not if len(download_directory) >= 0 and download_directory[-1] != '/': download_directory += '/' if not os.path.exists(download_directory): os.makedirs(download_directory) else: download_directory = '' if args.uri: songs = fetch_tracks(sp, playlist_id, current_user_id) else: songs = fetch_tracks(sp, args.playlist, current_user_id) url = [] for song, artist in songs.items(): link = fetch_youtube_url(song + ' - ' + artist) if link: url.append((link, song, artist)) save_songs_to_file(url, download_directory) if args.download is True: download_songs(url, download_directory, args.format_str[0], args.skip_mp3)
def test_spotify_album_fetch(): sp = spotify_auth() url = "https://open.spotify.com/album/1IVEQdX6Y37za9PMB0afPX?si=Hz8CMaYpTx2O0PeuDglKaA" item_type = "album" songs = fetch_tracks(sp, item_type, url) assert {'Simple Song': 'The Shins'} == songs
def test_spotify_album_fetch_more(): sp = spotify_auth() url = "https://open.spotify.com/album/2RKEso6nin3nhRyAd36Omv?si=KEBaFQxYR9-nRJLarH2QNQ" item_type = "album" songs = fetch_tracks(sp, item_type, url) assert [{ 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Procession - Remastered 2011', 'num': 1, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Father To Son - Remastered 2011', 'num': 2, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'White Queen (As It Began) - Remastered 2011', 'num': 3, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Some Day One Day - Remastered 2011', 'num': 4, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'The Loser In The End - Remastered 2011', 'num': 5, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Ogre Battle - Remastered 2011', 'num': 6, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': "The Fairy Feller's Master-Stroke - Remastered 2011", 'num': 7, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Nevermore - Remastered 2011', 'num': 8, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'The March Of The Black Queen - Remastered 2011', 'num': 9, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Funny How Love Is - Remastered 2011', 'num': 10, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Seven Seas Of Rhye - Remastered 2011', 'num': 11, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': "See What A Fool I've Been - Live BBC Session, London / July 1973 / " '2011 Remix', 'num': 1, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'White Queen (As It Began) - Live At Hammersmith Odeon, London / ' 'December 1975', 'num': 2, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Seven Seas Of Rhye - Instrumental Mix 2011', 'num': 3, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'Nevermore - Live BBC Session, London / April 1974', 'num': 4, 'num_tracks': 16, 'year': '1974' }, { 'album': 'Queen II (Deluxe Remastered Version)', 'artist': 'Queen', 'cover': 'https://i.scdn.co/image/ab67616d0000b273dcf482c792ef848d7a994fd5', 'genre': 'classic rock', 'name': 'See What A Fool I’ve Been - B-Side Version / Remastered 2011', 'num': 5, 'num_tracks': 16, 'year': '1974' }] == songs assert (len(songs)) == 16
def test_spotify_playlist_fetch(): sp = spotify_auth() url = "https://open.spotify.com/playlist/1EqaIF6DswCUE0I6gAzQQv?si=9BzJyGNRSGOZ-nsL66WmmA" item_type = "playlist" songs = fetch_tracks(sp, item_type, url) assert {'Hotel California - Live On MTV, 1994': 'Eagles'} == songs