-
Notifications
You must be signed in to change notification settings - Fork 0
/
create_playlist.py
192 lines (159 loc) · 6.89 KB
/
create_playlist.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
import json
import requests
class CreatePlaylist:
def __init__(self):
self.user_id = None
self.spotify_token = None
self.songs = {}
def set_credentials(self, user_id: str, spotify_token: str):
"""Sets user_id and spotify_token attributes in the CreatePlaylist class
Parameters:
user_id (str): Spotify User ID of the person creating the playlist
spotify_token (str): access token provided by Spotify that lasts 1 hour
"""
self.user_id = user_id
self.spotify_token = spotify_token
def create_playlist(
self, is_public_playlist: bool, playlist_name: str, playlist_description: str
) -> str:
"""Creates a new Spotify playlist and returns the playlist ID
Parameters:
is_public_playlist (bool): A boolean depicting if the playlist is public
playlist_name (str): the name of the playlist on Spotify (default "New Playlist")
playlist_description (str): the description of the playlist on Spotify (default "New playlist for songs using https://create-spotify-playlist.herokuapp.com/")
Returns:
playlist_id (str): The ID of the created Spotify playlist, automatically generated by Spotify
"""
playlist_name = playlist_name if playlist_name else "New Playlist"
playlist_description = (
playlist_description
if playlist_description
else "New playlist for songs using https://create-spotify-playlist.herokuapp.com/"
)
request_body = json.dumps(
{
"name": playlist_name,
"description": playlist_description,
"public": str(is_public_playlist).lower(),
}
)
query = f"https://api.spotify.com/v1/users/{self.user_id}/playlists"
response = requests.post(
query,
data=request_body,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {self.spotify_token}",
},
)
response_json = response.json()
if "id" not in response_json:
raise Exception("Invalid token and username")
playlist_id = response_json["id"]
return playlist_id
def get_spotify_uri(self, song_name: str, artist: str) -> str:
"""Search for a song on Spotify and returns the URI if found
Parameters:
song_name (str): the name of the song being looked up
artist (str): the name of the artist that wrote the song
Returns:
uri (str): the URI of the song from Spotify's API
Raises:
Exception: if no results were returned by Spotify's API
"""
query = f"https://api.spotify.com/v1/search?query=track%3A{song_name}+artist%3A{artist}&type=track&offset=0&limit=20"
try:
response = requests.get(
query,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {self.spotify_token}",
},
)
response_json = response.json()
songs = response_json["tracks"]["items"]
# only use the first song
uri = songs[0]["uri"]
return uri
except Exception:
return
def get_submitted_song_names(
self,
submitted_songs: str,
timestamp_del: str,
artist_song_del: str,
artist_before_song: bool,
):
"""Parses out the user-submitted songs and appends it to the songs class attribute
Parameters:
submitted_songs (str): a string containing multiple song/artist names
timestamp_del (str): the delimeter that is used to parse out the YouTube timestamps
artist_song_del (str): the delimeter that is used to split artist names from song names
artist_before_song (bool): if the artist name goes before the song name
"""
lines = submitted_songs.splitlines()
for line in lines:
if timestamp_del:
line = line.strip().split(timestamp_del, 1)[1].strip()
line = line.split(artist_song_del)
if artist_before_song:
artist = line[0].strip()
song_name = line[1].strip()
else:
artist = line[1].strip()
song_name = line[0].strip()
# skip missing song or artist
if song_name is not None and artist is not None:
# skip song with missing uri
spotify_uri = self.get_spotify_uri(song_name, artist)
if spotify_uri:
self.songs[song_name] = {
"artist": artist,
"song_name": song_name,
"spotify_uri": spotify_uri,
}
def add_submitted_songs_to_playlist(
self,
submitted_songs: str,
timestamp_del: str,
artist_song_del: str,
playlist_name: str,
playlist_description: str,
artist_before_song: bool,
is_public_playlist: bool,
):
"""Creates a new playlist on Spotify that contains the user-inputted songs
Parameters:
submitted_songs (str): a string containing multiple song/artist names
timestamp_del (str): the delimeter that is used to parse out the YouTube timestamps
artist_song_del (str): the delimeter that is used to split artist names from song names
playlist_name (str): the name of the playlist on Spotify (default "New Playlist")
playlist_description (str): the description of the playlist on Spotify (default "New playlist for songs using https://create-spotify-playlist.herokuapp.com/")
artist_before_song (bool): if the artist name goes before the song name
is_public_playlist (bool): A boolean depicting if the playlist is public
Returns:
response_json
"""
# get songs into songs dictionary
self.get_submitted_song_names(
submitted_songs, timestamp_del, artist_song_del, artist_before_song
)
# collect all of the URIs
uris = [info["spotify_uri"] for song, info in self.songs.items()]
# create a new playlist
playlist_id = self.create_playlist(
is_public_playlist, playlist_name, playlist_description
)
# add all songs into new playlist
request_data = json.dumps(uris)
query = f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks"
response = requests.post(
query,
data=request_data,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {self.spotify_token}",
},
)
response_json = response.json()
return response_json