def getSong(spotifyAccount: spotipy.Spotify): results = spotifyAccount.current_user_playing_track() item = results['item'] albumData = item['album'] artist = albumData['artists'][0]['name'] albumName = albumData['name'] songName = item['name'] genius = lyricsgenius.Genius(client_genius_secret) return Song(artist, albumName, songName, genius, results['progress_ms'], item['duration_ms'])
class Client: def __init__(self, api_id: str, api_secret: str, redirect_uri: str, username: str, update_time: int) -> None: self.client_id = api_id self.client_secret = api_secret self.redirect_uri = redirect_uri self.username = username self.update_time = update_time self._client: Spotify = None def init(self): auth_manager = SpotifyOAuth(client_id=self.client_id, client_secret=self.client_secret, redirect_uri=self.redirect_uri, scope="user-read-currently-playing", username=self.username) self._client = Spotify(auth_manager=auth_manager) return self._client def get_current_track(self): track = self._client.current_user_playing_track() if not track: return Track() song = track['item'] if not song: return Track() return Track(song['id'], song['name'], song['artists'][0]['name'], song['album']['images'][0]['url'], track['is_playing']) def wait_for_new_track(self, last_track_id): track = self.get_current_track() while track.playing and track.id == last_track_id: time.sleep(self.update_time) track = self.get_current_track() def wait_for_track_play(self): track = self.get_current_track() while not track.playing: time.sleep(self.update_time) track = self.get_current_track()
class _ThingSpotifyImpl(_ThingSpotifyDummy): def __init__(self, api_base_url, tok): super().__init__(api_base_url) self._sp = Spotify(auth=tok) self.unmuted_vol_pct = 0 self.volume_up_pct_delta = 10 self.status_cache_seconds = 10 self.last_status = None self.last_status_t = 0 def playpause(self): if self._is_active(): self._sp.pause_playback() else: self._sp.start_playback() def stop(self): self._sp.pause_playback() def play_next_in_queue(self): self._sp.next_track() def play_prev_in_queue(self): # First 'prev' just moves playtime back to 0 self._sp.previous_track() self._sp.previous_track() def set_playtime(self, t): if not self._is_active(): return self._sp.seek_track(int(t) * 1000) def volume_up(self): if not self._is_active(): return vol = self._get_volume_pct() + self.volume_up_pct_delta if vol > 100: vol = 100 self.set_volume_pct(vol) def volume_down(self): if not self._is_active(): return vol = self._get_volume_pct() - self.volume_up_pct_delta if vol < 0: vol = 0 self.set_volume_pct(vol) def set_volume_pct(self, pct): if not self._is_active(): return self._sp.volume(int(pct)) def toggle_mute(self): if not self._is_active(): return vol = self._get_volume_pct() if vol == 0: self.set_volume_pct(self.unmuted_vol_pct) else: self.unmuted_vol_pct = vol self.set_volume_pct(0) def play_in_device(self, dev_name): devs = self._sp.devices()['devices'] for dev in devs: if dev['name'] == dev_name: self._sp.transfer_playback(dev['id']) if self.json_status(nocache=True)['player_state'] != 'Playing': self.playpause() return raise KeyError("Spotify knows no device called {}".format(dev_name)) def _get_volume_pct(self): l = [ x for x in self._sp.devices()['devices'] if x['is_active'] == True ] if len(l) == 0: return 0 return l[0]['volume_percent'] def _is_active(self): track = self._sp.current_user_playing_track() return (track is not None) and track['is_playing'] def json_status(self, nocache=False): global LAST_ACTIVE_DEVICE if nocache == False and self.last_status is not None: if time.time() - self.last_status_t < self.status_cache_seconds: logger.debug("Return Spotify status from cache") return self.last_status self.last_status_t = time.time() devices = self._sp.devices()['devices'] active_dev = None if len(devices) > 0: act_devs = [x for x in devices if x['is_active'] == True] if len(act_devs) > 0: active_dev = act_devs[0] if active_dev is not None: LAST_ACTIVE_DEVICE = active_dev['name'] vol = active_dev['volume_percent'] if active_dev is not None else 0 track = self._sp.current_user_playing_track() is_active = (track is not None) and track['is_playing'] self.last_status = { 'name': self.get_id(), 'uri': None, 'active_device': active_dev['name'] if active_dev is not None else None, 'last_active_device': LAST_ACTIVE_DEVICE, 'available_devices': [x['name'] for x in devices], 'app': None, 'volume_pct': vol, 'volume_muted': (vol == 0), 'player_state': 'Playing' if is_active else 'Idle', 'media': None, } if track is None or track['item'] is None: return self.last_status # Get all cover images sorted by image size imgs = [] try: imgs = [(img['height'] * img['width'], img['url']) for img in track['item']['album']['images']] imgs.sort() except: pass # Pick an image that's at least 300*300 (or the biggest, if all are smaller) selected_img = None for img in imgs: area, selected_img = img if area >= 90000: break self.last_status['media'] = { 'icon': selected_img, 'title': track['item']['name'], 'duration': track['item']['duration_ms'] / 1000, 'current_time': track['progress_ms'] / 1000, 'spotify_metadata': { 'artist': ', '.join( [x['name'] for x in track['item']['album']['artists']]), 'album_link': track['item']['album']['external_urls']['spotify'], 'album_name': track['item']['album']['name'], 'track_count': track['item']['album']['total_tracks'], 'current_track': track['item']['track_number'], } } return self.last_status
def get_playing_track(sp: Spotify) -> Dict[str, Any]: """Get user's currently playing track""" return sp.current_user_playing_track()
sp_oauth = SpotifyOAuth(cache_path=environ['SPOTIPY_CACHE_PATH'], scope=scope) try: tokens = sp_oauth.get_access_token(code=authorization_code, as_dict=True) except Exception as e: tokens = sp_oauth.refresh_access_token( sp_oauth.get_cached_token()['refresh_token']) expires_at = tokens['expires_at'] artists_names = [] artists_urls = [] if expires_at > int(datetime.now().strftime('%s')): sp = Spotify(auth_manager=sp_oauth) last_updated = datetime.now(tz=utc).strftime('%Y-%m-%d %H:%M:%S %Z') currently_playing = sp.current_user_playing_track() if currently_playing: song_name = currently_playing['item']['name'] song_url = currently_playing['item']['external_urls']['spotify'] album_name = currently_playing['item']['album']['external_urls'][ 'spotify'] album_image_url = currently_playing['item']['album']['images'][0][ 'url'] artists = currently_playing['item']['artists'] if len(artists) > 1: for artist in artists: artists_names.append(artist['name']) artists_urls.append(artist['external_urls']['spotify']) else: artists_names.append(artists[0]['name']) artists_urls.append(artists[0]['external_urls']['spotify'])
def update_job(self): def update_color_caller(): self.set_color((0, 0, 0)) self.set_color_palette([]) token = util.prompt_for_user_token( Config.SPOTIFY_USERNAME, "user-read-playback-state", client_id=Config.SPOTIFY_CLIENT_ID, client_secret=Config.SPOTIFY_CLIENT_SECRET, redirect_uri=Config.SPOTIFY_REDIRECT_URI, ) sp = Spotify(auth=token) current_track = sp.current_user_playing_track() if (current_track is None or not current_track["is_playing"] or current_track["item"] is None): job = self.scheduler.get_job("color_updater") if job is not None: job.remove() if job is not None or self.current_track is not None: self.set_color((0, 0, 0)) self.set_color_palette([]) self.set_is_playing(False) self.set_current_track_title("") return track_id = current_track["item"]["id"] if self.current_track is None: self.set_is_playing(True) if self.current_track != track_id: self.current_track = track_id cover_urls = current_track["item"]["album"]["images"] cover_url = cover_urls[0]["url"] response = requests.get(cover_url) response.raise_for_status() image = Image.open(BytesIO(response.content)) self.set_color(self.color_finder.get_most_prominent_color(image)) self.set_color_palette(self.get_color_palette(image)) self.set_current_track_title(current_track["item"]["name"]) # One cannot use this as this is not correct # now = datetime.fromtimestamp(current_track['timestamp'] / 1000) now = datetime.now() start_of_track = now - timedelta( milliseconds=current_track["progress_ms"]) next_change = start_of_track + timedelta( milliseconds=current_track["item"]["duration_ms"]) self.scheduler.add_job( update_color_caller, "date", (), id="color_updater", run_date=next_change, replace_existing=True, )