mirror of
https://github.com/cooperhammond/irs.git
synced 2025-01-08 20:05:27 +00:00
Downloading of spotify playlists is a go.
This commit is contained in:
parent
a05d7dfdc8
commit
fbe3edf1ef
70
README.md
70
README.md
|
@ -2,97 +2,85 @@
|
|||
[![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)
|
||||
|
||||
<em>Now with working album art!</em>
|
||||
|
||||
<em>Downloading of Spotify playlists coming soon!</em>
|
||||
<em>Spotify playlists are now downloadable!</em>
|
||||
|
||||
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
|
||||
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"
|
||||
```
|
||||
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/8kb9882j4cbtd4hwbsbb7h0ia.png)](https://asciinema.org/a/8kb9882j4cbtd4hwbsbb7h0ia?speed=3)
|
||||
|
||||
Full usage:
|
||||
```
|
||||
usage:
|
||||
usage:
|
||||
irs (-h | -v)
|
||||
irs [-l]
|
||||
irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
|
||||
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
|
||||
irs -p PLAYLIST [-c COMMAND] [-l]
|
||||
irs -A ALBUM [-c COMMAND] [-l]
|
||||
irs -a ARTIST -s SONG [-c COMMAND] [-l]
|
||||
|
||||
Options:
|
||||
-h, --help show this help message 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
|
||||
Run a background command with each song's location.
|
||||
Example: `-c "rhythmbox %(loc)s"`
|
||||
-a ARTIST, --artist ARTIST
|
||||
Specify the artist name.
|
||||
-p PLAYLIST, --playlist PLAYLIST
|
||||
Specify playlist filename. Each line in the file
|
||||
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.
|
||||
Specify the artist name. Only needed for -s/--song
|
||||
-s SONG, --song SONG Specify song name of the artist. Must be used with
|
||||
-a/--artist
|
||||
-l, --choose-link If supplied, will bring up a console choice for what
|
||||
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
|
||||
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`:
|
||||
```
|
||||
$ brew install ffmpeg
|
||||
brew install ffmpeg
|
||||
```
|
||||
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.
|
||||
|
||||
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
|
||||
- [x] Finds album based off of song name and artist
|
||||
- [x] Full album downloading
|
||||
- [x] Album art metadata correctly displayed
|
||||
- [x] Playlist downloading
|
||||
- [ ] Spotify playlist downloading - <em>Coming soon</em>
|
||||
- [x] Spotify playlist downloading
|
||||
- [ ] GUI/Console interactive version - <em>In progress</em>
|
||||
- [ ] 100% success rate for automatic song choosing
|
||||
|
|
|
@ -2,29 +2,37 @@
|
|||
HELP = \
|
||||
"""
|
||||
usage:
|
||||
irs (-h | -v)
|
||||
irs (-h | -v | -C)
|
||||
irs [-l]
|
||||
irs -p PLAYLIST [-ng] [-c COMMAND] [-l]
|
||||
irs -a ARTIST (-s SONG | -A ALBUM [-st SEARCH_TERMS]) [-c COMMAND] [-l]
|
||||
irs -p PLAYLIST [-c COMMAND] [-l]
|
||||
irs -A ALBUM [-c COMMAND] [-l]
|
||||
irs -a ARTIST -s SONG [-c COMMAND] [-l]
|
||||
|
||||
Options:
|
||||
-h, --help show this help message 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
|
||||
Run a background command with each song's location.
|
||||
Example: `-c "rhythmbox %(loc)s"`
|
||||
|
||||
-a ARTIST, --artist ARTIST
|
||||
Specify the artist name.
|
||||
-p PLAYLIST, --playlist PLAYLIST
|
||||
Specify playlist filename. Each line in the file
|
||||
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.
|
||||
Specify the artist name. Only needed for -s/--song
|
||||
|
||||
-s SONG, --song SONG Specify song name of the artist. Must be used with
|
||||
-a/--artist
|
||||
|
||||
-l, --choose-link If supplied, will bring up a console choice for what
|
||||
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
|
||||
|
@ -36,11 +44,14 @@ import argparse
|
|||
# Import the manager
|
||||
from .manager import Manager
|
||||
from .utils import *
|
||||
from .config import CONFIG
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
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('-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('-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.")
|
||||
|
||||
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()
|
||||
args = parser.parse_args(sys.argv[1:] + CONFIG["default_flags"].split(" ")[:-1])
|
||||
|
||||
if args.organize == None:
|
||||
args.organize = True
|
||||
|
@ -82,23 +90,25 @@ def main():
|
|||
print ("\n")
|
||||
exit(0)
|
||||
|
||||
elif args.config:
|
||||
print (get_config_file_path())
|
||||
|
||||
elif not args.organize and not args.playlist:
|
||||
parser.error("error: must supply -p/--playlist if specifying -ng/--no-organize")
|
||||
exit(1)
|
||||
|
||||
elif args.artist and not (args.album or args.song):
|
||||
parser.error("error: must supply -A/--album or -s/--song if specifying -a/--artist")
|
||||
exit(1)
|
||||
#elif args.artist and not (args.album or args.song):
|
||||
# parser.error("error: must supply -A/--album or -s/--song if specifying -a/--artist")
|
||||
# exit(1)
|
||||
|
||||
elif args.playlist:
|
||||
manager.rip_playlist()
|
||||
manager.rip_spotify_list("playlist")
|
||||
|
||||
elif args.artist:
|
||||
if args.album:
|
||||
manager.rip_album()
|
||||
elif args.album:
|
||||
manager.rip_spotify_list("album")
|
||||
|
||||
elif args.song:
|
||||
manager.rip_mp3()
|
||||
elif args.song:
|
||||
manager.rip_mp3()
|
||||
|
||||
else:
|
||||
manager.console()
|
||||
|
|
19
irs/config.py
Normal file
19
irs/config.py
Normal 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,
|
||||
)
|
221
irs/manager.py
221
irs/manager.py
|
@ -1,5 +1,6 @@
|
|||
# Powered by:
|
||||
import youtube_dl
|
||||
from spotipy.oauth2 import SpotifyClientCredentials
|
||||
import spotipy
|
||||
|
||||
# Info getting
|
||||
|
@ -14,6 +15,7 @@ from bs4 import BeautifulSoup
|
|||
# Local utils
|
||||
from .utils import *
|
||||
from .metadata import *
|
||||
from .config import CONFIG
|
||||
|
||||
class Manager:
|
||||
def __init__(self, args):
|
||||
|
@ -40,31 +42,18 @@ class Manager:
|
|||
except ValueError:
|
||||
print (bc.FAIL + "\nPlease enter a valid number." + bc.ENDC)
|
||||
|
||||
if media in (1, 2):
|
||||
self.args.artist = color_input("Artist of song/album")
|
||||
if media == 1:
|
||||
self.args.song = color_input("Song you would like to download")
|
||||
self.rip_mp3()
|
||||
|
||||
if media == 1:
|
||||
self.args.song = color_input("Song you would like to download")
|
||||
self.rip_mp3()
|
||||
|
||||
elif media == 2:
|
||||
self.args.album = color_input("Album you would like to download")
|
||||
self.rip_album()
|
||||
elif media == 2:
|
||||
self.args.album = color_input("Album you would like to download")
|
||||
self.rip_spotify_list("album")
|
||||
|
||||
elif media == 3:
|
||||
self.args.playlist = color_input("Playlist file name")
|
||||
self.args.playlist = color_input("Playlist name to search for")
|
||||
|
||||
organize = ""
|
||||
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()
|
||||
self.rip_spotify_list("playlist")
|
||||
|
||||
def find_mp3(self, song=None, artist=None):
|
||||
if not song:
|
||||
|
@ -131,85 +120,6 @@ class Manager:
|
|||
|
||||
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):
|
||||
spotify = spotipy.Spotify()
|
||||
|
||||
|
@ -223,48 +133,92 @@ class Manager:
|
|||
album = items[0]['images'][0]['url']
|
||||
return album
|
||||
|
||||
def rip_spotify_list(self, search, type, id=None):
|
||||
spotify = spotipy.Spotify()
|
||||
def rip_spotify_list(self, type):
|
||||
|
||||
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)
|
||||
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:
|
||||
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:
|
||||
print (bc.FAIL + "No results were found." + 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)
|
||||
print (bc.FAIL + "No results were found. Make sure to use proper spelling and capitalization." + bc.ENDC)
|
||||
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,
|
||||
album=None, # if you want to specify an album and save a bit of time.
|
||||
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.
|
||||
organize=True
|
||||
):
|
||||
|
||||
|
||||
if not song:
|
||||
song = self.args.song
|
||||
|
||||
|
@ -273,7 +227,12 @@ class Manager:
|
|||
|
||||
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 = {
|
||||
'format': 'bestaudio/best',
|
||||
|
@ -288,13 +247,13 @@ class Manager:
|
|||
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):
|
||||
os.makedirs(artist_folder)
|
||||
|
||||
if album:
|
||||
album_folder = artist + "/" + album
|
||||
album_folder = CONFIG["directory"] + "/" + artist + "/" + album
|
||||
if not os.path.isdir(album_folder):
|
||||
os.makedirs(album_folder)
|
||||
location = album_folder
|
||||
|
|
52
irs/utils.py
52
irs/utils.py
|
@ -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):
|
||||
special_chars = "\ / : * ? \" < > | - ( )".split(" ")
|
||||
|
@ -111,19 +114,50 @@ def finish_unorganize(file_name):
|
|||
|
||||
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):
|
||||
spotify = spotipy.Spotify()
|
||||
|
||||
thelist = list(thelist)
|
||||
print ("Results:")
|
||||
choice = ""
|
||||
while choice not in tuple(range(0, len(thelist[:5]))):
|
||||
for index, album in enumerate(thelist[:5]):
|
||||
info = spotify.user(album["owner"]["id"])
|
||||
try:
|
||||
display_info = " (" + str(info["followers"]["total"]) + " followers)" + " - " + info["display_name"]
|
||||
except Exception:
|
||||
display_info = " - info couldn't be found"
|
||||
while choice not in tuple(range(0, len(thelist[:10]))):
|
||||
for index, result in enumerate(thelist[:10]):
|
||||
type = result["type"]
|
||||
|
||||
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))
|
||||
|
||||
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()
|
||||
|
|
2
setup.py
2
setup.py
|
@ -2,7 +2,7 @@ from setuptools import setup
|
|||
|
||||
setup(
|
||||
name='irs',
|
||||
version='2.7.20',
|
||||
version='3.7.20',
|
||||
description='A music downloader that just gets metadata.',
|
||||
url='https://github.com/kepoorhampond/irs',
|
||||
author='Kepoor Hampond',
|
||||
|
|
76
test1.py
76
test1.py
|
@ -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"))
|
Loading…
Reference in a new issue