-
Notifications
You must be signed in to change notification settings - Fork 0
/
spotifyauth.py
157 lines (114 loc) · 4.9 KB
/
spotifyauth.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
import spotipy
import os
import spotipy.util as util
from http.server import HTTPServer, BaseHTTPRequestHandler
from threading import Thread
# os.environ["SPOTIPY_CLIENT_ID"] = ""
# os.environ["SPOTIPY_CLIENT_SECRET"] = ""
SERVER_PORT = 14523
os.environ["SPOTIPY_REDIRECT_URI"] = "http://localhost:{}".format(SERVER_PORT)
scope = 'user-library-read playlist-read-private playlist-read-collaborative playlist-modify-public playlist-modify-private'
class FailedAuth(BaseException):
"""Failed authentication for spotify"""
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)
class NotFound(BaseException):
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)
class MyHTTPHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write('<html><body><h1 style="text-align:center">Great! Now go back to the python program and insert the URL of this page:</h1><button onclick="copy()" style="margin: 0 auto;display:block">Copy to clipboard</button><textarea id="textarea" style="display: block; margin: 0 auto; width: 60%"></textarea><script>var txt = document.getElementById("textarea"); txt.value = window.location.href;txt.select();function copy() {txt.select();document.execCommand("copy");}</script></body></html>'.encode('utf-8'))
def log_message(self, format, *args):
return
class StoppableSilentHTTPServer(HTTPServer):
stopped = False
def __init__(self, *args, **kw):
HTTPServer.__init__(self, *args, **kw)
def serve_forever(self):
while not self.stopped:
self.handle_request()
def force_stop(self):
self.stopped = True
self.server_close()
class SpotifyAuth:
def __init__(self, username):
self._username = username
self._sp = None
def wait_for_auth(self):
self.httpd = StoppableSilentHTTPServer(('', SERVER_PORT), MyHTTPHandler)
Thread(target=self.httpd.serve_forever).start()
token = util.prompt_for_user_token(self._username, scope)
if token:
self._sp = spotipy.Spotify(auth=token)
else:
raise FailedAuth
def get_spotify(self):
return self._sp
def stop_server(self):
self.httpd.force_stop()
def __list_add_tracks__(list_object, tracks):
for item in tracks["items"]:
track = item["track"]
if track["id"] is not None:
list_object.append(track["id"])
return list_object
def __add_playlist__(playlist_list, playlists):
for item in playlists["items"]:
playlist_list.append(item)
return playlist_list
def __chunk_list__(data, size):
return [data[x:x + size] for x in range(0, len(data), size)]
class SpotifyTool:
def __init__(self, username, sp):
self._username = username
self._sp = sp
self._playlist = None
self._user_playlists = None
def get_user_playlists(self):
if self._user_playlists is None:
playlist_list = []
playlists = self._sp.user_playlists(self._username)
__add_playlist__(playlist_list, playlists)
while playlists["next"]:
playlists = self._sp.next(playlists)
__add_playlist__(playlist_list, playlists)
self._user_playlists = playlist_list
return self._user_playlists
def set_playlist_by_id(self, playlist_id):
try:
self._playlist = self._sp.user_playlist(self._username, playlist_id)
except BaseException:
raise NotFound("No playlist found")
if self._playlist is None:
raise NotFound("No playlist found")
def set_playlist_by_name(self, name, ignore_case = False):
self._playlist = self.__find_playlist__(name, ignore_case)
if self._playlist is None:
raise NotFound("No playlist found")
def __find_playlist__(self, name, ignore_case = False):
playlists = self.get_user_playlists()
for item in playlists:
if ignore_case:
if item["name"].lower() == name.lower():
return item
else:
if item["name"] == name:
return item
return None
def get_playlist_tracks(self):
results = self._sp.user_playlist_tracks(self._username, self._playlist['id'])
tracks = results['items']
while results['next']:
results = self._sp.next(results)
tracks.extend(results['items'])
return tracks
def remove_specific_track(self, id, pos):
self._sp.user_playlist_remove_specific_occurrences_of_tracks(self._username, self._playlist['id'],
[{'uri': id, 'positions': [pos]}])