Split spotify functions

This commit is contained in:
ritiek
2018-01-09 15:26:42 +05:30
parent cb738ca731
commit a6028e2155
3 changed files with 146 additions and 134 deletions

View File

@@ -117,15 +117,6 @@ def sanitize_title(title):
return title return title
def generate_token():
""" Generate the token. Please respect these credentials :) """
credentials = oauth2.SpotifyClientCredentials(
client_id='4fe3fecfe5334023a1472516cc99d805',
client_secret='0f02b7c483c04257984695007a4a8d5c')
token = credentials.get_access_token()
return token
def filter_path(path): def filter_path(path):
if not os.path.exists(path): if not os.path.exists(path):
os.makedirs(path) os.makedirs(path)

138
core/spotify_tools.py Normal file
View File

@@ -0,0 +1,138 @@
import spotipy
import spotipy.oauth2 as oauth2
from titlecase import titlecase
import pprint
from core import internals
from core import logger
log = logger.log
def generate_token():
""" Generate the token. Please respect these credentials :) """
credentials = oauth2.SpotifyClientCredentials(
client_id='4fe3fecfe5334023a1472516cc99d805',
client_secret='0f02b7c483c04257984695007a4a8d5c')
token = credentials.get_access_token()
return token
token = generate_token()
spotify = spotipy.Spotify(auth=token)
def generate_metadata(raw_song):
""" Fetch a song's metadata from Spotify. """
if internals.is_spotify(raw_song):
# fetch track information directly if it is spotify link
log.debug('Fetching metadata for given track URL')
meta_tags = spotify.track(raw_song)
else:
# otherwise search on spotify and fetch information from first result
log.debug('Searching for "{}" on Spotify'.format(raw_song))
try:
meta_tags = spotify.search(raw_song, limit=1)['tracks']['items'][0]
except IndexError:
return None
artist = spotify.artist(meta_tags['artists'][0]['id'])
album = spotify.album(meta_tags['album']['id'])
try:
meta_tags[u'genre'] = titlecase(artist['genres'][0])
except IndexError:
meta_tags[u'genre'] = None
try:
meta_tags[u'copyright'] = album['copyrights'][0]['text']
except IndexError:
meta_tags[u'copyright'] = None
try:
meta_tags[u'external_ids'][u'isrc']
except KeyError:
meta_tags[u'external_ids'][u'isrc'] = None
meta_tags[u'release_date'] = album['release_date']
meta_tags[u'publisher'] = album['label']
meta_tags[u'total_tracks'] = album['tracks']['total']
log.debug(pprint.pformat(meta_tags))
return meta_tags
def feed_playlist(username):
""" Fetch user playlists when using the -u option. """
playlists = spotify.user_playlists(username)
links = []
check = 1
while True:
for playlist in playlists['items']:
# 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:
log.info(u'{0:>5}. {1:<30} ({2} tracks)'.format(
check, playlist['name'],
playlist['tracks']['total']))
log.debug(playlist['external_urls']['spotify'])
links.append(playlist)
check += 1
if playlists['next']:
playlists = spotify.next(playlists)
else:
break
playlist = internals.input_link(links)
write_playlist(playlist['owner']['id'], playlist['id'])
def write_tracks(text_file, tracks):
with open(text_file, 'a') as file_out:
while True:
for item in tracks['items']:
if 'track' in item:
track = item['track']
else:
track = item
try:
track_url = track['external_urls']['spotify']
file_out.write(track_url + '\n')
log.debug(track_url)
except KeyError:
log.warning(u'Skipping track {0} by {1} (local only?)'.format(
track['name'], track['artists'][0]['name']))
# 1 page = 50 results
# check if there are more pages
if tracks['next']:
tracks = spotify.next(tracks)
else:
break
def write_playlist(username, playlist_id):
results = spotify.user_playlist(username, playlist_id,
fields='tracks,next,name')
text_file = u'{0}.txt'.format(slugify(results['name'], ok='-_()[]{}'))
log.info(u'Writing {0} tracks to {1}'.format(
results['tracks']['total'], text_file))
tracks = results['tracks']
write_tracks(text_file, tracks)
def write_album(album):
tracks = spotify.album_tracks(album['id'])
text_file = u'{0}.txt'.format(slugify(album['name'], ok='-_()[]{}'))
log.info(u'writing {0} tracks to {1}'.format(
tracks['total'], text_file))
write_tracks(text_file, tracks)
def grab_album(album):
if '/' in album:
if album.endswith('/'):
playlist = playlist[:-1]
splits = album.split('/')
else:
splits = album.split(':')
album_id = splits[-1]
album = spotify.album(album_id)
write_album(album)

133
spotdl.py
View File

@@ -5,6 +5,7 @@ from core import logger
from core import metadata from core import metadata
from core import convert from core import convert
from core import internals from core import internals
from core import spotify_tools
from titlecase import titlecase from titlecase import titlecase
from slugify import slugify from slugify import slugify
import spotipy import spotipy
@@ -24,43 +25,6 @@ def generate_songname(tags):
return raw_song return raw_song
def generate_metadata(raw_song):
""" Fetch a song's metadata from Spotify. """
if internals.is_spotify(raw_song):
# fetch track information directly if it is spotify link
log.debug('Fetching metadata for given track URL')
meta_tags = spotify.track(raw_song)
else:
# otherwise search on spotify and fetch information from first result
log.debug('Searching for "{}" on Spotify'.format(raw_song))
try:
meta_tags = spotify.search(raw_song, limit=1)['tracks']['items'][0]
except IndexError:
return None
artist = spotify.artist(meta_tags['artists'][0]['id'])
album = spotify.album(meta_tags['album']['id'])
try:
meta_tags[u'genre'] = titlecase(artist['genres'][0])
except IndexError:
meta_tags[u'genre'] = None
try:
meta_tags[u'copyright'] = album['copyrights'][0]['text']
except IndexError:
meta_tags[u'copyright'] = None
try:
meta_tags[u'external_ids'][u'isrc']
except KeyError:
meta_tags[u'external_ids'][u'isrc'] = None
meta_tags[u'release_date'] = album['release_date']
meta_tags[u'publisher'] = album['label']
meta_tags[u'total_tracks'] = album['tracks']['total']
log.debug(pprint.pformat(meta_tags))
return meta_tags
def is_video(result): def is_video(result):
# ensure result is not a channel # ensure result is not a channel
not_video = result.find('channel') is not None or \ not_video = result.find('channel') is not None or \
@@ -193,73 +157,6 @@ def get_youtube_title(content, number=None):
return '{0}. {1}'.format(number, title) return '{0}. {1}'.format(number, title)
def feed_playlist(username):
""" Fetch user playlists when using the -u option. """
playlists = spotify.user_playlists(username)
links = []
check = 1
while True:
for playlist in playlists['items']:
# 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:
log.info(u'{0:>5}. {1:<30} ({2} tracks)'.format(
check, playlist['name'],
playlist['tracks']['total']))
log.debug(playlist['external_urls']['spotify'])
links.append(playlist)
check += 1
if playlists['next']:
playlists = spotify.next(playlists)
else:
break
playlist = internals.input_link(links)
write_playlist(playlist['owner']['id'], playlist['id'])
def write_tracks(text_file, tracks):
with open(text_file, 'a') as file_out:
while True:
for item in tracks['items']:
if 'track' in item:
track = item['track']
else:
track = item
try:
track_url = track['external_urls']['spotify']
file_out.write(track_url + '\n')
log.debug(track_url)
except KeyError:
log.warning(u'Skipping track {0} by {1} (local only?)'.format(
track['name'], track['artists'][0]['name']))
# 1 page = 50 results
# check if there are more pages
if tracks['next']:
tracks = spotify.next(tracks)
else:
break
def write_playlist(username, playlist_id):
results = spotify.user_playlist(username, playlist_id,
fields='tracks,next,name')
text_file = u'{0}.txt'.format(slugify(results['name'], ok='-_()[]{}'))
log.info(u'Writing {0} tracks to {1}'.format(
results['tracks']['total'], text_file))
tracks = results['tracks']
write_tracks(text_file, tracks)
def write_album(album):
tracks = spotify.album_tracks(album['id'])
text_file = u'{0}.txt'.format(slugify(album['name'], ok='-_()[]{}'))
log.info(u'writing {0} tracks to {1}'.format(
tracks['total'], text_file))
write_tracks(text_file, tracks)
def download_song(file_name, content): def download_song(file_name, content):
""" Download the audio file from YouTube. """ """ Download the audio file from YouTube. """
if args.input_ext in (".webm", ".m4a"): if args.input_ext in (".webm", ".m4a"):
@@ -342,7 +239,7 @@ def grab_list(text_file):
except spotipy.client.SpotifyException: except spotipy.client.SpotifyException:
# refresh token when it expires # refresh token when it expires
log.debug('Token expired, generating new one and authorizing') log.debug('Token expired, generating new one and authorizing')
new_token = internals.generate_token() new_token = spotify_tools.generate_token()
global spotify global spotify
spotify = spotipy.Spotify(auth=new_token) spotify = spotipy.Spotify(auth=new_token)
grab_single(raw_song, number=number) grab_single(raw_song, number=number)
@@ -380,36 +277,22 @@ def grab_playlist(playlist):
sys.exit(10) sys.exit(10)
playlist_id = splits[-1] playlist_id = splits[-1]
try: try:
write_playlist(username, playlist_id) spotify_tools.write_playlist(username, playlist_id)
except spotipy.client.SpotifyException: except spotipy.client.SpotifyException:
log.error('Unable to find playlist') log.error('Unable to find playlist')
log.info('Make sure the playlist is set to publicly visible and then try again') log.info('Make sure the playlist is set to publicly visible and then try again')
sys.exit(11) sys.exit(11)
def grab_album(album):
if '/' in album:
if album.endswith('/'):
playlist = playlist[:-1]
splits = album.split('/')
else:
splits = album.split(':')
album_id = splits[-1]
album = spotify.album(album_id)
write_album(album)
def grab_single(raw_song, number=None): def grab_single(raw_song, number=None):
""" Logic behind downloading a song. """ """ Logic behind downloading a song. """
if internals.is_youtube(raw_song): if internals.is_youtube(raw_song):
log.debug('Input song is a YouTube URL') log.debug('Input song is a YouTube URL')
content = go_pafy(raw_song, meta_tags=None) content = go_pafy(raw_song, meta_tags=None)
raw_song = slugify(content.title).replace('-', ' ') raw_song = slugify(content.title).replace('-', ' ')
meta_tags = generate_metadata(raw_song) meta_tags = spotify_tools.generate_metadata(raw_song)
else: else:
meta_tags = generate_metadata(raw_song) meta_tags = spotify_tools.generate_metadata(raw_song)
content = go_pafy(raw_song, meta_tags) content = go_pafy(raw_song, meta_tags)
if content is None: if content is None:
@@ -460,7 +343,7 @@ def grab_single(raw_song, number=None):
# token is mandatory when using Spotify's API # token is mandatory when using Spotify's API
# https://developer.spotify.com/news-stories/2017/01/27/removing-unauthenticated-calls-to-the-web-api/ # https://developer.spotify.com/news-stories/2017/01/27/removing-unauthenticated-calls-to-the-web-api/
token = internals.generate_token() token = spotify_tools.generate_token()
spotify = spotipy.Spotify(auth=token) spotify = spotipy.Spotify(auth=token)
if __name__ == '__main__': if __name__ == '__main__':
@@ -482,9 +365,9 @@ if __name__ == '__main__':
elif args.playlist: elif args.playlist:
grab_playlist(playlist=args.playlist) grab_playlist(playlist=args.playlist)
elif args.album: elif args.album:
grab_album(album=args.album) spotify_tools.grab_album(album=args.album)
elif args.username: elif args.username:
feed_playlist(username=args.username) spotify_tools.feed_playlist(username=args.username)
# Actually we don't necessarily need this, but yeah... # Actually we don't necessarily need this, but yeah...
# Explicit is better than implicit! # Explicit is better than implicit!