Downloading of spotify playlists is a go.

This commit is contained in:
Kepoor Hampond 2017-01-25 20:57:56 -08:00
parent a05d7dfdc8
commit fbe3edf1ef
7 changed files with 217 additions and 283 deletions

View file

@ -2,97 +2,85 @@
[![License: GNU](https://img.shields.io/badge/License-GNU-yellow.svg)](http://www.gnu.org/licenses/gpl.html) [![License: GNU](https://img.shields.io/badge/License-GNU-yellow.svg)](http://www.gnu.org/licenses/gpl.html)
[![PyPI](https://img.shields.io/badge/PyPi-Python_3.x-blue.svg)](https://pypi.python.org/pypi/irs) [![PyPI](https://img.shields.io/badge/PyPi-Python_3.x-blue.svg)](https://pypi.python.org/pypi/irs)
<em>Now with working album art!</em> <em>Spotify playlists are now downloadable!</em>
<em>Downloading of Spotify playlists coming soon!</em>
An ironically named program to download audio from youtube and then parse metadata for the downloaded file. An ironically named program to download audio from youtube and then parse metadata for the downloaded file.
___ ___
### Why the name?
As an acronym, it spells IRS. I think this is breathtakingly hilarious because the Internal Revenue Service (also the IRS) takes away, while my program gives. I'm so funny. You can tell that I'll get laid in college.
### Usage and Examples ### Usage and Examples
To download a specific song, you'll want to use the `-s` flag: To download Spotify playlists, you need to supply client_ids. To do this, you'll want to create an application [here](https://developer.spotify.com/my-applications/#!/applications/create). Once you've done that, you'll want to copy your 'client id' and your 'client secret' into the config file and their corresponding lines. To find the config file run this command: `irs -C`. If that's all working, enter the name of the playlist you would like to download like this:
```bash
irs -p "Brain Food"
``` ```
If you download a specific song, you'll want to use the `-s` and `-a` flag.
```bash
irs -a "David Bowie" -s "Ziggy Stardust" irs -a "David Bowie" -s "Ziggy Stardust"
``` ```
To download an entire album, you'll want to use the `-A` flag: To download an entire album, you'll want to use the `-A` flag. If the album you want can't be found, run it with the `-a` flag for some more specification.
```bash
irs -A "Sadnecessary" # -a "Milky Chance"
``` ```
irs -a "Milky Chance" -A "Sadnecessary"
```
If you want to download a playlist, you'll need to make a text file, such as `Awesome Mix.txt`. In the file, you'll want to write songs into it like this:
```
Hot Blood - Kaleo
Work Song - Hozier
Drop The Game - Flume & Chet Faker
```
Then, run a command like this where the playlist file resides:
```
irs -p "Awesome Mix.txt"
```
[![asciicast](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug.png)](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug?speed=3&autoplay=true) [![asciicast](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug.png)](https://asciinema.org/a/bcs7i0sjmka052wsdyxg5xrug?speed=3&autoplay=true)
[![asciicast](https://asciinema.org/a/8kb9882j4cbtd4hwbsbb7h0ia.png)](https://asciinema.org/a/8kb9882j4cbtd4hwbsbb7h0ia?speed=3) [![asciicast](https://asciinema.org/a/8kb9882j4cbtd4hwbsbb7h0ia.png)](https://asciinema.org/a/8kb9882j4cbtd4hwbsbb7h0ia?speed=3)
Full usage: Full usage:
``` ```
usage:
usage: usage:
irs (-h | -v) irs (-h | -v)
irs [-l] irs [-l]
irs -p PLAYLIST [-ng] [-c COMMAND] [-l] irs -p PLAYLIST [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l] irs -A ALBUM [-c COMMAND] [-l]
irs -a ARTIST -s SONG [-c COMMAND] [-l]
Options: Options:
-h, --help show this help message and exit -h, --help show this help message and exit
-v, --version Display the version and exit. -v, --version Display the version and exit.
-A ALBUM, --album ALBUM
Search spotify for an album.
-p PLAYLIST, --playlist PLAYLIST
Search spotify for a playlist.
-c COMMAND, --command COMMAND -c COMMAND, --command COMMAND
Run a background command with each song's location. Run a background command with each song's location.
Example: `-c "rhythmbox %(loc)s"` Example: `-c "rhythmbox %(loc)s"`
-a ARTIST, --artist ARTIST -a ARTIST, --artist ARTIST
Specify the artist name. Specify the artist name. Only needed for -s/--song
-p PLAYLIST, --playlist PLAYLIST -s SONG, --song SONG Specify song name of the artist. Must be used with
Specify playlist filename. Each line in the file -a/--artist
should be formatted like so: `SONGNAME - ARTIST`
-s SONG, --song SONG Specify song name of the artist.
-A ALBUM, --album ALBUM
Specify album name of the artist.
-st SEARCH_TERMS, --search-terms SEARCH_TERMS
Only use if calling -A/--album. Acts as extra search
terms when looking for the album.
-l, --choose-link If supplied, will bring up a console choice for what -l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles. link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
``` ```
___ ___
### Installation ### Installation
Please note that it currently is only usable in `Python 3.x`. Almost all dependencies are automatically installed by pip, but `youtube_dl` still needs `ffmpeg` to convert video to audio, so for Windows, you can install [`Scoop`](http://scoop.sh/) and then just do: Please note that it currently is only usable in `Python 3.x`. Almost all dependencies are automatically installed by pip, but `youtube_dl` still needs `ffmpeg` to convert video to audio, so for Windows, you can install [`Scoop`](http://scoop.sh/) and then just do:
``` ```
$ scoop install ffmpeg scoop install ffmpeg
``` ```
For OSX, you can use [`Brew`](http://brew.sh/) to install `ffmpeg`: For OSX, you can use [`Brew`](http://brew.sh/) to install `ffmpeg`:
``` ```
$ brew install ffmpeg brew install ffmpeg
``` ```
And then for Ubuntu: And then for Ubuntu:
``` ```
$ sudo apt-get install ffmpeg sudo apt-get install ffmpeg
``` ```
Most other linux distros have `ffmpeg` or `libav-tools` in their package manager repos, so you can install one or the other for other distros. Most other linux distros have `ffmpeg` or `libav-tools` in their package manager repos, so you can install one or the other for other distros.
Finally, install it! Finally, install it!
``` ```
$ pip install irs pip install irs
``` ```
### Why the name?
As an acronym, it spells IRS. I think this is breathtakingly hilarious because the Internal Revenue Service (also the IRS) takes away, while my program gives. I'm so funny. You can tell that I'll get laid in college.
### Wishlist ### Wishlist
- [x] Finds album based off of song name and artist - [x] Finds album based off of song name and artist
- [x] Full album downloading - [x] Full album downloading
- [x] Album art metadata correctly displayed - [x] Album art metadata correctly displayed
- [x] Playlist downloading - [x] Playlist downloading
- [ ] Spotify playlist downloading - <em>Coming soon</em> - [x] Spotify playlist downloading
- [ ] GUI/Console interactive version - <em>In progress</em> - [ ] GUI/Console interactive version - <em>In progress</em>
- [ ] 100% success rate for automatic song choosing - [ ] 100% success rate for automatic song choosing

View file

@ -2,29 +2,37 @@
HELP = \ HELP = \
""" """
usage: usage:
irs (-h | -v) irs (-h | -v | -C)
irs [-l] irs [-l]
irs -p PLAYLIST [-ng] [-c COMMAND] [-l] irs -p PLAYLIST [-c COMMAND] [-l]
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l] irs -A ALBUM [-c COMMAND] [-l]
irs -a ARTIST -s SONG [-c COMMAND] [-l]
Options: Options:
-h, --help show this help message and exit -h, --help show this help message and exit
-v, --version Display the version and exit. -v, --version Display the version and exit.
-C, --config Return location of configuration file.
-A ALBUM, --album ALBUM
Search spotify for an album.
-p PLAYLIST, --playlist PLAYLIST
Search spotify for a playlist.
-c COMMAND, --command COMMAND -c COMMAND, --command COMMAND
Run a background command with each song's location. Run a background command with each song's location.
Example: `-c "rhythmbox %(loc)s"` Example: `-c "rhythmbox %(loc)s"`
-a ARTIST, --artist ARTIST -a ARTIST, --artist ARTIST
Specify the artist name. Specify the artist name. Only needed for -s/--song
-p PLAYLIST, --playlist PLAYLIST
Specify playlist filename. Each line in the file -s SONG, --song SONG Specify song name of the artist. Must be used with
should be formatted like so: `SONGNAME - ARTIST` -a/--artist
-s SONG, --song SONG Specify song name of the artist.
-A ALBUM, --album ALBUM
Specify album name of the artist.
-l, --choose-link If supplied, will bring up a console choice for what -l, --choose-link If supplied, will bring up a console choice for what
link you want to download based off a list of titles. link you want to download based off a list of titles.
-ng, --no-organize Only use if calling -p/--playlist. Forces all files
downloaded to be organized normally.
""" """
# For exiting # For exiting
@ -36,11 +44,14 @@ import argparse
# Import the manager # Import the manager
from .manager import Manager from .manager import Manager
from .utils import * from .utils import *
from .config import CONFIG
def main(): def main():
parser = argparse.ArgumentParser(add_help=False) parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-h', '--help', action='store_true', dest='help') parser.add_argument('-h', '--help', action='store_true', dest='help')
parser.add_argument('-v', '--version', dest="version", action='store_true', help="Display the version and exit.") parser.add_argument('-v', '--version', dest="version", action='store_true', help="Display the version and exit.")
parser.add_argument('-C', '--config', dest="config", action='store_true', help="Return config file location.")
parser.add_argument('-c', '--command', dest="command", help="Run a background command with each song's location.") parser.add_argument('-c', '--command', dest="command", help="Run a background command with each song's location.")
parser.add_argument('-a', '--artist', dest="artist", help="Specify the artist name.") parser.add_argument('-a', '--artist', dest="artist", help="Specify the artist name.")
@ -57,11 +68,8 @@ def main():
media.add_argument('-A', '--album', dest="album", help="Specify album name of the artist.") media.add_argument('-A', '--album', dest="album", help="Specify album name of the artist.")
parser.add_argument('-o', '--order-files', action='store_true', dest="order_files",\
help="Only use if callign with -p/--playlist or -A/--album. Adds a digit to front of each file specifying order.")
args = parser.parse_args(sys.argv[1:] + CONFIG["default_flags"].split(" ")[:-1])
args = parser.parse_args()
if args.organize == None: if args.organize == None:
args.organize = True args.organize = True
@ -82,23 +90,25 @@ def main():
print ("\n") print ("\n")
exit(0) exit(0)
elif args.config:
print (get_config_file_path())
elif not args.organize and not args.playlist: elif not args.organize and not args.playlist:
parser.error("error: must supply -p/--playlist if specifying -ng/--no-organize") parser.error("error: must supply -p/--playlist if specifying -ng/--no-organize")
exit(1) exit(1)
elif args.artist and not (args.album or args.song): #elif args.artist and not (args.album or args.song):
parser.error("error: must supply -A/--album or -s/--song if specifying -a/--artist") # parser.error("error: must supply -A/--album or -s/--song if specifying -a/--artist")
exit(1) # exit(1)
elif args.playlist: elif args.playlist:
manager.rip_playlist() manager.rip_spotify_list("playlist")
elif args.artist: elif args.album:
if args.album: manager.rip_spotify_list("album")
manager.rip_album()
elif args.song: elif args.song:
manager.rip_mp3() manager.rip_mp3()
else: else:
manager.console() manager.console()

19
irs/config.py Normal file
View file

@ -0,0 +1,19 @@
CONFIG = dict(
# To autostart rhythmbox with a new song:
# default_flags = '-c rhythmbox %(loc)s',
# To make choosing of links default:
# default_flags = '-l',
default_flags = '',
# These are necessary to download Spotify playlists
client_id = '',
client_secret = '',
# For a custom directory. Note that `~` will not work as a shortcut.
directory = '',
# If you want numbered file names
numbered_file_names = True,
)

View file

@ -1,5 +1,6 @@
# Powered by: # Powered by:
import youtube_dl import youtube_dl
from spotipy.oauth2 import SpotifyClientCredentials
import spotipy import spotipy
# Info getting # Info getting
@ -14,6 +15,7 @@ from bs4 import BeautifulSoup
# Local utils # Local utils
from .utils import * from .utils import *
from .metadata import * from .metadata import *
from .config import CONFIG
class Manager: class Manager:
def __init__(self, args): def __init__(self, args):
@ -40,31 +42,18 @@ class Manager:
except ValueError: except ValueError:
print (bc.FAIL + "\nPlease enter a valid number." + bc.ENDC) print (bc.FAIL + "\nPlease enter a valid number." + bc.ENDC)
if media in (1, 2): if media == 1:
self.args.artist = color_input("Artist of song/album") self.args.song = color_input("Song you would like to download")
self.rip_mp3()
if media == 1: elif media == 2:
self.args.song = color_input("Song you would like to download") self.args.album = color_input("Album you would like to download")
self.rip_mp3() self.rip_spotify_list("album")
elif media == 2:
self.args.album = color_input("Album you would like to download")
self.rip_album()
elif media == 3: elif media == 3:
self.args.playlist = color_input("Playlist file name") self.args.playlist = color_input("Playlist name to search for")
organize = "" self.rip_spotify_list("playlist")
while organize not in ("y", "n", "yes", "no", ""):
print (bc.HEADER + "Would you like to place all songs into a single folder? (Y/n)", end="")
organize = input(bc.BOLD + bc.YELLOW + ": " + bc.ENDC).lower()
if organize in ("y", "yes", ""):
self.args.organize = True
elif organize in ("n", "no"):
self.args.organize = False
self.rip_playlist()
def find_mp3(self, song=None, artist=None): def find_mp3(self, song=None, artist=None):
if not song: if not song:
@ -131,85 +120,6 @@ class Manager:
return search_results[i] return search_results[i]
def rip_playlist(self):
file_name = self.args.playlist
organize = self.args.organize
try:
file = open(file_name, 'r')
except Exception:
print (file_name + bc.FAIL + " could not be found." + bc.ENDC)
exit(1)
errors = []
song_number = 0
for line in file:
if line.strip() == "":
pass
#try:
arr = line.strip("\n").split(" - ")
self.args.song = arr[0]
self.args.artist = arr[1]
if os.path.isdir(self.args.artist):
remove = False
else:
remove = True
location = self.rip_mp3()
locations = location.split("/")
song_number += 1
# Enter... the reorganizing...
if organize:
folder_name = ("playlist - " + file_name)[:40]
if not os.path.isdir(folder_name):
os.makedirs(folder_name)
os.rename(location, "%s/%s - %s" % (folder_name, song_number, locations[-1]))
if remove:
import shutil # Only import this if I have to.
shutil.rmtree(locations[0])
if organize:
os.rename(file_name, folder_name + "/" + file_name)
os.rename(folder_name, folder_name.replace("playlist - ", ""))
#except Exception as e:
# errors.append(line + color(" : ", ["YELLOW"]) + bc.FAIL + str(e) + bc.ENDC)
if len(errors) > 0:
print (bc.FAIL + "Something was wrong with the formatting of the following lines:" + bc.ENDC)
for i in errors:
print ("\t%s" % i)
def get_album_contents(self, search):
spotify = spotipy.Spotify()
results = spotify.search(q=search, type='album')
items = results['albums']['items']
if len(items) > 0:
album = choose_from_list(items)
album_id = (album['uri'])
contents = spotify.album_tracks(album_id)["items"]
contents = contents[0:-1]
names = []
for song in contents:
song = song["name"]
names.append(song)
return names, album_id
else:
print (bc.FAIL + "There was no results." + bc.ENDC)
exit(1)
def get_album_art(self, artist, album, id=None): def get_album_art(self, artist, album, id=None):
spotify = spotipy.Spotify() spotify = spotipy.Spotify()
@ -223,48 +133,92 @@ class Manager:
album = items[0]['images'][0]['url'] album = items[0]['images'][0]['url']
return album return album
def rip_spotify_list(self, search, type, id=None): def rip_spotify_list(self, type):
spotify = spotipy.Spotify()
if type == "playlist":
search = self.args.playlist
elif type == "album":
search = self.args.album
if self.args.artist:
search += self.args.artist
try:
client_credentials_manager = SpotifyClientCredentials(CONFIG["client_id"], CONFIG["client_secret"])
spotify = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
except spotipy.oauth2.SpotifyOauthError:
spotify = spotipy.Spotify()
results = spotify.search(q=search, type=type) results = spotify.search(q=search, type=type)
items = results[type + "s"]['items'] items = results[type + "s"]['items']
songs = []
if len(items) > 0: if len(items) > 0:
spotify_list = choose_from_spotify_list(items) spotify_list = choose_from_spotify_list(items)
list_type = spotify_list["type"]
if list_type != "playlist":
spotify_list = eval("spotify.%s" % list_type)(spotify_list["uri"])
else:
try:
spotify_list = spotify.user_playlist(spotify_list["owner"]["id"], \
playlist_id=spotify_list["uri"], fields="tracks,next")
except spotipy.client.SpotifyException:
fail_oauth()
print (bc.YELLOW + "\nFetching tracks and their metadata: " + bc.ENDC)
increment = 0
for song in spotify_list["tracks"]["items"]:
increment += 1
list_size = increment / len(spotify_list["tracks"]["items"])
drawProgressBar(list_size)
if list_type == "playlist":
song = song["track"]
artist = spotify.artist(song["artists"][0]["id"])
if list_type == "playlist":
album = (spotify.track(song["uri"])["album"])
else:
album = spotify_list
songs.append({
"name": song["name"],
"artist": artist["name"],
"album": album["name"],
"tracknum": song["track_number"],
"album_cover": album["images"][0]["url"]
})
print (bc.OKGREEN + "\nFound tracks:" + bc.ENDC)
print (bc.HEADER)
for song in songs:
print ("\t" + song["name"] + " - " + song["artist"])
print (bc.ENDC + "\n")
for song in songs:
self.rip_mp3(song["name"], song["artist"], album=song["album"], \
tracknum=song["tracknum"], album_art_url=song["album_cover"])
else: else:
print (bc.FAIL + "No results were found." + bc.ENDC) print (bc.FAIL + "No results were found. Make sure to use proper spelling and capitalization." + bc.ENDC)
def rip_album(self):
search = self.args.artist + " " + self.args.album
songs, album_uri = self.get_album_contents(search)
if not songs:
print (bc.FAIL + "Could not find album." + bc.ENDC)
exit(1) exit(1)
print ("")
print (bc.HEADER + "Album Contents:" + bc.ENDC)
for song in songs:
print (bc.OKBLUE + " - " + song + bc.ENDC)
print (bc.YELLOW + "\nFinding album cover ... " + bc.ENDC, end="\r")
album_art_url = self.get_album_art(self.args.artist, self.args.album, id=album_uri)
print (bc.OKGREEN + "Album cover found: " + bc.ENDC + album_art_url)
for track_number, song in enumerate(songs):
print (color("\n%s/%s - " % (track_number + 1, len(songs)), ["UNDERLINE"]), end="")
self.rip_mp3(song, album=self.args.album, tracknum=track_number + 1, album_art_url=album_art_url)
else:
print (bc.BOLD + bc.UNDERLINE + self.args.album + bc.ENDC + bc.OKGREEN + " downloaded successfully!\n")
def rip_mp3(self, song=None, artist=None, def rip_mp3(self, song=None, artist=None,
album=None, # if you want to specify an album and save a bit of time. album=None, # if you want to specify an album and save a bit of time.
tracknum=None, # to specify the tracknumber in the album. tracknum=None, # to specify the tracknumber in the album.
album_art_url=None, # if you want to save a lot of time trying to find album cover. album_art_url=None, # if you want to save a lot of time trying to find album cover.
organize=True
): ):
if not song: if not song:
song = self.args.song song = self.args.song
@ -273,7 +227,12 @@ class Manager:
audio_code = self.find_mp3(song=song, artist=artist) audio_code = self.find_mp3(song=song, artist=artist)
filename = strip_special_chars(song) + ".mp3" if CONFIG["numbered_file_names"] and tracknum:
track = str(tracknum) + " - "
else:
track = ""
filename = track + strip_special_chars(song) + ".mp3"
ydl_opts = { ydl_opts = {
'format': 'bestaudio/best', 'format': 'bestaudio/best',
@ -288,13 +247,13 @@ class Manager:
ydl.download(["http://www.youtube.com/watch?v=" + audio_code]) ydl.download(["http://www.youtube.com/watch?v=" + audio_code])
artist_folder = artist artist_folder = CONFIG["directory"] + "/" + artist
if not os.path.isdir(artist_folder): if not os.path.isdir(artist_folder):
os.makedirs(artist_folder) os.makedirs(artist_folder)
if album: if album:
album_folder = artist + "/" + album album_folder = CONFIG["directory"] + "/" + artist + "/" + album
if not os.path.isdir(album_folder): if not os.path.isdir(album_folder):
os.makedirs(album_folder) os.makedirs(album_folder)
location = album_folder location = album_folder

View file

@ -1,4 +1,7 @@
import sys, os import sys, os, spotipy, irs
def get_config_file_path():
return os.path.dirname(irs.__file__) + "/config.py"
def strip_special_chars(string): def strip_special_chars(string):
special_chars = "\ / : * ? \" < > | - ( )".split(" ") special_chars = "\ / : * ? \" < > | - ( )".split(" ")
@ -111,19 +114,50 @@ def finish_unorganize(file_name):
os.rename(folder_name, folder_name.replace("playlist - ", "")) os.rename(folder_name, folder_name.replace("playlist - ", ""))
def fail_oauth():
print (bc.FAIL + "To download Spotify playlists, you need to supply client_ids." + bc.ENDC)
print ("To do this, you'll want to create an application here:")
print ("https://developer.spotify.com/my-applications/#!/applications/create")
print ("Once you've done that, you'll want to copy your 'client id' and your 'client secret'")
print ("into the config file and their corresponding locations:")
print (get_config_file_path())
exit(1)
def choose_from_spotify_list(thelist): def choose_from_spotify_list(thelist):
spotify = spotipy.Spotify()
thelist = list(thelist) thelist = list(thelist)
print ("Results:") print ("Results:")
choice = "" choice = ""
while choice not in tuple(range(0, len(thelist[:5]))): while choice not in tuple(range(0, len(thelist[:10]))):
for index, album in enumerate(thelist[:5]): for index, result in enumerate(thelist[:10]):
info = spotify.user(album["owner"]["id"]) type = result["type"]
try:
display_info = " (" + str(info["followers"]["total"]) + " followers)" + " - " + info["display_name"]
except Exception:
display_info = " - info couldn't be found"
print ("\t" + str(index) + ") " + album["name"] + display_info) if type == "playlist":
info = spotify.user(result["owner"]["id"])
try:
display_info = " (" + str(info["followers"]["total"]) + " followers)"
display_info += " - " + info["display_name"]
except Exception:
display_info = " - info couldn't be found"
elif type == "album":
info = spotify.album(result["id"])
display_info = " - " + info["artists"][0]["name"]
print ("\t" + str(index) + ") " + result["name"] + display_info)
choice = int(input(bc.YELLOW + "\nEnter result number: " + bc.ENDC)) choice = int(input(bc.YELLOW + "\nEnter result number: " + bc.ENDC))
return thelist[choice] return thelist[choice]
def drawProgressBar(percent, barLen = 40):
import sys
sys.stdout.write("\r")
progress = ""
for i in range(barLen):
if i < int(barLen * percent):
progress += "#"
else:
progress += "-"
sys.stdout.write("[%s] %.2f%%" % (progress, percent * 100))
sys.stdout.flush()

View file

@ -2,7 +2,7 @@ from setuptools import setup
setup( setup(
name='irs', name='irs',
version='2.7.20', version='3.7.20',
description='A music downloader that just gets metadata.', description='A music downloader that just gets metadata.',
url='https://github.com/kepoorhampond/irs', url='https://github.com/kepoorhampond/irs',
author='Kepoor Hampond', author='Kepoor Hampond',

View file

@ -1,76 +0,0 @@
class bc:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKGREEN = '\033[32m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'
GRAY = '\033[30m'
YELLOW = '\033[33m'
def choose_from_spotify_list(thelist):
thelist = list(thelist)
print ("Results:")
choice = ""
while choice not in tuple(range(0, len(thelist[:5]))):
for index, result in enumerate(thelist[:5]):
type = result["type"]
if type == "playlist":
info = spotify.user(result["owner"]["id"])
try:
display_info = " (" + str(info["followers"]["total"]) + " followers)"
display_info += " - " + info["display_name"]
except Exception:
display_info = " - info couldn't be found"
elif type == "album":
info = spotify.album(result["id"])
display_info = " - " + info["artists"][0]["name"]
print ("\t" + str(index) + ") " + result["name"] + display_info)
choice = int(input(bc.YELLOW + "\nEnter result number: " + bc.ENDC))
return thelist[choice]
def rip_spotify_list(search, type, id=None):
spotify = spotipy.Spotify()
results = spotify.search(q=search, type=type)
items = results[type + "s"]['items']
songs = []
if len(items) > 0:
spotify_list = choose_from_spotify_list(items)
list_type = spotify_list["type"]
if list_type != "playlist":
spotify_list = eval("spotify.%s" % list_type)(spotify_list["uri"])
else:
try:
spotify_list = spotify.user_playlist(spotify_list["owner"]["id"], \
playlist_id=spotify_list["uri"], fields="tracks,next")
except spotipy.client.SpotifyException:
print (bc.FAIL + "To download Spotify playlists, you need to supply client_id's" + bc.ENDC)
exit(1)
print (bc.YELLOW + "\nFetching tracks ..." + bc.ENDC, end="\r")
for song in spotify_list["tracks"]["items"]:
artist = spotify.artist(song["artists"][0]["id"])
songs.append([song["name"], artist["name"]])
print (bc.OKGREEN + "Found tracks!" + bc.ENDC)
return songs
else:
print (bc.FAIL + "No results were found." + bc.ENDC)
exit(1)
import spotipy
spotify = spotipy.Spotify()
#results = spotify.search(q="Star Wars Headspace", type="album")
#results = results["albums"]["items"]
print (rip_spotify_list("Brain Food", "playlist"))