def get_current_playback(): spotify_id = request.args.get('spotify_id') playlist_id = request.args.get('playlist_id') if playlist_id: db = Database(Config.DATABASE_PATH) token = db.get_host_token(playlist_id) spotify = Spotify(auth=token) playback = spotify.current_playback() return create_response(playback) elif spotify_id: db = Database(Config.DATABASE_PATH) token = db.get_user_token(spotify_id) spotify = Spotify(auth=token) playback = spotify.current_playback() return create_response(playback) return jsonify({'Error': 'Invalid or missing spotify id'})
def getCurrentPlaybackInfo(user: spotipy.Spotify): currentPlayback = user.current_playback() if currentPlayback and currentPlayback["currently_playing_type"] == "track": song = currentPlayback["item"]["name"] song_id = currentPlayback["item"]["id"] artists = [ artist["name"] for artist in currentPlayback["item"]["artists"] ] album = currentPlayback["item"]["album"]["name"] cover_url = currentPlayback["item"]["album"]["images"][-1]["url"] length_ms = currentPlayback["item"]["duration_ms"] position = currentPlayback["progress_ms"] print( f"{song} - {', '.join(artists)}: {position/1000}/{length_ms/1000}, {cover_url}" )
def akttym(): SCOPE = 'user-library-modify,user-read-playback-state' dir_path = os.path.dirname(os.path.realpath(__file__)) config = yaml.safe_load(open(dir_path + '/config.yaml')) check_config(config, dir_path) token = util.prompt_for_user_token(config['username'], SCOPE, client_id=config['client_id'], client_secret=config['client_secret'], redirect_uri='http://localhost:1911/', cache_path=dir_path + '/cache') if token: sp = Spotify(auth=token) track = sp.current_playback() if track is not None: sp.current_user_saved_tracks_add([track['item']['id']]) logging.warning("added %s to %s's library", track['item']['name'], config['username']) else: logging.warning("nothing is playing currently, aborting") else: logging.warning("Can't get token for %s", config['username'])
class SpotifyMediaPlayer(MediaPlayerEntity): """Representation of a Spotify controller.""" def __init__( self, session: OAuth2Session, spotify: Spotify, me: dict, user_id: str, name: str, ): """Initialize.""" self._id = user_id self._me = me self._name = f"Spotify {name}" self._session = session self._spotify = spotify self._scope_ok = set( session.token["scope"].split(" ")) == set(SPOTIFY_SCOPES) self._currently_playing: Optional[dict] = {} self._devices: Optional[List[dict]] = [] self._playlist: Optional[dict] = None self._spotify: Spotify = None self.player_available = False @property def name(self) -> str: """Return the name.""" return self._name @property def icon(self) -> str: """Return the icon.""" return ICON @property def available(self) -> bool: """Return True if entity is available.""" return self.player_available @property def unique_id(self) -> str: """Return the unique ID.""" return self._id @property def device_info(self) -> Dict[str, Any]: """Return device information about this entity.""" if self._me is not None: model = self._me["product"] return { "identifiers": {(DOMAIN, self._id)}, "manufacturer": "Spotify AB", "model": f"Spotify {model}".rstrip(), "name": self._name, } @property def state(self) -> Optional[str]: """Return the playback state.""" if not self._currently_playing: return STATE_IDLE if self._currently_playing["is_playing"]: return STATE_PLAYING return STATE_PAUSED @property def volume_level(self) -> Optional[float]: """Return the device volume.""" return self._currently_playing.get("device", {}).get( "volume_percent", 0) / 100 @property def media_content_id(self) -> Optional[str]: """Return the media URL.""" item = self._currently_playing.get("item") or {} return item.get("uri") @property def media_content_type(self) -> Optional[str]: """Return the media type.""" return MEDIA_TYPE_MUSIC @property def media_duration(self) -> Optional[int]: """Duration of current playing media in seconds.""" if self._currently_playing.get("item") is None: return None return self._currently_playing["item"]["duration_ms"] / 1000 @property def media_position(self) -> Optional[str]: """Position of current playing media in seconds.""" if not self._currently_playing: return None return self._currently_playing["progress_ms"] / 1000 @property def media_position_updated_at(self) -> Optional[dt.datetime]: """When was the position of the current playing media valid.""" if not self._currently_playing: return None return utc_from_timestamp(self._currently_playing["timestamp"] / 1000) @property def media_image_url(self) -> Optional[str]: """Return the media image URL.""" if (self._currently_playing.get("item") is None or not self._currently_playing["item"]["album"]["images"]): return None return fetch_image_url(self._currently_playing["item"]["album"]) @property def media_image_remotely_accessible(self) -> bool: """If the image url is remotely accessible.""" return False @property def media_title(self) -> Optional[str]: """Return the media title.""" item = self._currently_playing.get("item") or {} return item.get("name") @property def media_artist(self) -> Optional[str]: """Return the media artist.""" if self._currently_playing.get("item") is None: return None return ", ".join([ artist["name"] for artist in self._currently_playing["item"]["artists"] ]) @property def media_album_name(self) -> Optional[str]: """Return the media album.""" if self._currently_playing.get("item") is None: return None return self._currently_playing["item"]["album"]["name"] @property def media_track(self) -> Optional[int]: """Track number of current playing media, music track only.""" item = self._currently_playing.get("item") or {} return item.get("track_number") @property def media_playlist(self): """Title of Playlist currently playing.""" if self._playlist is None: return None return self._playlist["name"] @property def source(self) -> Optional[str]: """Return the current playback device.""" return self._currently_playing.get("device", {}).get("name") @property def source_list(self) -> Optional[List[str]]: """Return a list of source devices.""" if not self._devices: return None return [device["name"] for device in self._devices] @property def shuffle(self) -> bool: """Shuffling state.""" return bool(self._currently_playing.get("shuffle_state")) @property def supported_features(self) -> int: """Return the media player features that are supported.""" if self._me["product"] != "premium": return 0 return SUPPORT_SPOTIFY @spotify_exception_handler def set_volume_level(self, volume: int) -> None: """Set the volume level.""" self._spotify.volume(int(volume * 100)) @spotify_exception_handler def media_play(self) -> None: """Start or resume playback.""" self._spotify.start_playback() @spotify_exception_handler def media_pause(self) -> None: """Pause playback.""" self._spotify.pause_playback() @spotify_exception_handler def media_previous_track(self) -> None: """Skip to previous track.""" self._spotify.previous_track() @spotify_exception_handler def media_next_track(self) -> None: """Skip to next track.""" self._spotify.next_track() @spotify_exception_handler def media_seek(self, position): """Send seek command.""" self._spotify.seek_track(int(position * 1000)) @spotify_exception_handler def play_media(self, media_type: str, media_id: str, **kwargs) -> None: """Play media.""" kwargs = {} # Spotify can't handle URI's with query strings or anchors # Yet, they do generate those types of URI in their official clients. media_id = str(URL(media_id).with_query(None).with_fragment(None)) if media_type in (MEDIA_TYPE_TRACK, MEDIA_TYPE_EPISODE, MEDIA_TYPE_MUSIC): kwargs["uris"] = [media_id] elif media_type in PLAYABLE_MEDIA_TYPES: kwargs["context_uri"] = media_id else: _LOGGER.error("Media type %s is not supported", media_type) return if not self._currently_playing.get("device") and self._devices: kwargs["device_id"] = self._devices[0].get("id") self._spotify.start_playback(**kwargs) @spotify_exception_handler def select_source(self, source: str) -> None: """Select playback device.""" for device in self._devices: if device["name"] == source: self._spotify.transfer_playback(device["id"], self.state == STATE_PLAYING) return @spotify_exception_handler def set_shuffle(self, shuffle: bool) -> None: """Enable/Disable shuffle mode.""" self._spotify.shuffle(shuffle) @spotify_exception_handler def update(self) -> None: """Update state and attributes.""" if not self.enabled: return if not self._session.valid_token or self._spotify is None: run_coroutine_threadsafe(self._session.async_ensure_token_valid(), self.hass.loop).result() self._spotify = Spotify(auth=self._session.token["access_token"]) current = self._spotify.current_playback() self._currently_playing = current or {} self._playlist = None context = self._currently_playing.get("context") if context is not None and context["type"] == MEDIA_TYPE_PLAYLIST: self._playlist = self._spotify.playlist(current["context"]["uri"]) devices = self._spotify.devices() or {} self._devices = devices.get("devices", []) async def async_browse_media(self, media_content_type=None, media_content_id=None): """Implement the websocket media browsing helper.""" if not self._scope_ok: raise NotImplementedError if media_content_type in [None, "library"]: return await self.hass.async_add_executor_job(library_payload) payload = { "media_content_type": media_content_type, "media_content_id": media_content_id, } response = await self.hass.async_add_executor_job( build_item_response, self._spotify, self._me, payload) if response is None: raise BrowseError( f"Media not found: {media_content_type} / {media_content_id}") return response
class SpotifyMediaPlayer(MediaPlayerDevice): """Representation of a Spotify controller.""" def __init__(self, session, spotify: Spotify, me: dict, user_id: str, name: str): """Initialize.""" self._id = user_id self._me = me self._name = f"Spotify {name}" self._session = session self._spotify = spotify self._currently_playing: Optional[dict] = {} self._devices: Optional[List[dict]] = [] self._playlist: Optional[dict] = None self._spotify: Spotify = None self.player_available = False @property def name(self) -> str: """Return the name.""" return self._name @property def icon(self) -> str: """Return the icon.""" return ICON @property def available(self) -> bool: """Return True if entity is available.""" return self.player_available @property def unique_id(self) -> str: """Return the unique ID.""" return self._id @property def device_info(self) -> Dict[str, Any]: """Return device information about this entity.""" if self._me is not None: model = self._me["product"] return { "identifiers": {(DOMAIN, self._id)}, "manufacturer": "Spotify AB", "model": f"Spotify {model}".rstrip(), "name": self._name, } @property def state(self) -> Optional[str]: """Return the playback state.""" if not self._currently_playing: return STATE_IDLE if self._currently_playing["is_playing"]: return STATE_PLAYING return STATE_PAUSED @property def volume_level(self) -> Optional[float]: """Return the device volume.""" return self._currently_playing.get("device", {}).get( "volume_percent", 0) / 100 @property def media_content_id(self) -> Optional[str]: """Return the media URL.""" item = self._currently_playing.get("item") or {} return item.get("name") @property def media_content_type(self) -> Optional[str]: """Return the media type.""" return MEDIA_TYPE_MUSIC @property def media_duration(self) -> Optional[int]: """Duration of current playing media in seconds.""" if self._currently_playing.get("item") is None: return None return self._currently_playing["item"]["duration_ms"] / 1000 @property def media_position(self) -> Optional[str]: """Position of current playing media in seconds.""" if not self._currently_playing: return None return self._currently_playing["progress_ms"] / 1000 @property def media_position_updated_at(self) -> Optional[dt.datetime]: """When was the position of the current playing media valid.""" if not self._currently_playing: return None return utc_from_timestamp(self._currently_playing["timestamp"] / 1000) @property def media_image_url(self) -> Optional[str]: """Return the media image URL.""" if (self._currently_playing.get("item") is None or not self._currently_playing["item"]["album"]["images"]): return None return self._currently_playing["item"]["album"]["images"][0]["url"] @property def media_image_remotely_accessible(self) -> bool: """If the image url is remotely accessible.""" return False @property def media_title(self) -> Optional[str]: """Return the media title.""" item = self._currently_playing.get("item") or {} return item.get("name") @property def media_artist(self) -> Optional[str]: """Return the media artist.""" if self._currently_playing.get("item") is None: return None return ", ".join([ artist["name"] for artist in self._currently_playing["item"]["artists"] ]) @property def media_album_name(self) -> Optional[str]: """Return the media album.""" if self._currently_playing.get("item") is None: return None return self._currently_playing["item"]["album"]["name"] @property def media_track(self) -> Optional[int]: """Track number of current playing media, music track only.""" item = self._currently_playing.get("item") or {} return item.get("track_number") @property def media_playlist(self): """Title of Playlist currently playing.""" if self._playlist is None: return None return self._playlist["name"] @property def source(self) -> Optional[str]: """Return the current playback device.""" return self._currently_playing.get("device", {}).get("name") @property def source_list(self) -> Optional[List[str]]: """Return a list of source devices.""" if not self._devices: return None return [device["name"] for device in self._devices] @property def shuffle(self) -> bool: """Shuffling state.""" return bool(self._currently_playing.get("shuffle_state")) @property def supported_features(self) -> int: """Return the media player features that are supported.""" if self._me["product"] != "premium": return 0 return SUPPORT_SPOTIFY @spotify_exception_handler def set_volume_level(self, volume: int) -> None: """Set the volume level.""" self._spotify.volume(int(volume * 100)) @spotify_exception_handler def media_play(self) -> None: """Start or resume playback.""" self._spotify.start_playback() @spotify_exception_handler def media_pause(self) -> None: """Pause playback.""" self._spotify.pause_playback() @spotify_exception_handler def media_previous_track(self) -> None: """Skip to previous track.""" self._spotify.previous_track() @spotify_exception_handler def media_next_track(self) -> None: """Skip to next track.""" self._spotify.next_track() @spotify_exception_handler def media_seek(self, position): """Send seek command.""" self._spotify.seek_track(int(position * 1000)) @spotify_exception_handler def play_media(self, media_type: str, media_id: str, **kwargs) -> None: """Play media.""" kwargs = {} if media_type == MEDIA_TYPE_MUSIC: kwargs["uris"] = [media_id] elif media_type == MEDIA_TYPE_PLAYLIST: kwargs["context_uri"] = media_id else: _LOGGER.error("Media type %s is not supported", media_type) return self._spotify.start_playback(**kwargs) @spotify_exception_handler def select_source(self, source: str) -> None: """Select playback device.""" for device in self._devices: if device["name"] == source: self._spotify.transfer_playback(device["id"], self.state == STATE_PLAYING) return @spotify_exception_handler def set_shuffle(self, shuffle: bool) -> None: """Enable/Disable shuffle mode.""" self._spotify.shuffle(shuffle) @spotify_exception_handler def update(self) -> None: """Update state and attributes.""" if not self.enabled: return if not self._session.valid_token or self._spotify is None: run_coroutine_threadsafe(self._session.async_ensure_token_valid(), self.hass.loop).result() self._spotify = Spotify(auth=self._session.token["access_token"]) current = self._spotify.current_playback() self._currently_playing = current or {} self._playlist = None context = self._currently_playing.get("context") if context is not None and context["type"] == MEDIA_TYPE_PLAYLIST: self._playlist = self._spotify.playlist(current["context"]["uri"]) devices = self._spotify.devices() or {} self._devices = devices.get("devices", [])
class SpotifyMediaPlayer(MediaPlayerEntity): """Representation of a Spotify controller.""" _attr_icon = "mdi:spotify" _attr_media_content_type = MEDIA_TYPE_MUSIC _attr_media_image_remotely_accessible = False def __init__( self, session: OAuth2Session, spotify: Spotify, me: dict, # pylint: disable=invalid-name user_id: str, name: str, ) -> None: """Initialize.""" self._id = user_id self._me = me self._name = f"Spotify {name}" self._session = session self._spotify = spotify self._scope_ok = set( session.token["scope"].split(" ")).issuperset(SPOTIFY_SCOPES) self._currently_playing: dict | None = {} self._devices: list[dict] | None = [] self._playlist: dict | None = None self._attr_name = self._name self._attr_unique_id = user_id self._attr_last_selected = None self._attributes = {} @property def device_info(self) -> DeviceInfo: """Return device information about this entity.""" model = "Spotify Free" if self._me is not None: product = self._me["product"] model = f"Spotify {product}" return DeviceInfo( identifiers={(DOMAIN, self._id)}, manufacturer="Spotify AB", model=model, name=self._name, entry_type=DeviceEntryType.SERVICE, configuration_url="https://open.spotify.com", ) @property def state(self) -> str | None: """Return the playback state.""" if not self._currently_playing: return STATE_IDLE if self._currently_playing["is_playing"]: return STATE_PLAYING return STATE_PAUSED @property def volume_level(self) -> float | None: """Return the device volume.""" return self._currently_playing.get("device", {}).get( "volume_percent", 0) / 100 @property def media_content_id(self) -> str | None: """Return the media URL.""" item = self._currently_playing.get("item") or {} return item.get("uri") @property def media_duration(self) -> int | None: """Duration of current playing media in seconds.""" if self._currently_playing.get("item") is None: return None return self._currently_playing["item"]["duration_ms"] / 1000 @property def media_position(self) -> str | None: """Position of current playing media in seconds.""" if not self._currently_playing: return None return self._currently_playing["progress_ms"] / 1000 @property def media_position_updated_at(self) -> dt.datetime | None: """When was the position of the current playing media valid.""" if not self._currently_playing: return None return utc_from_timestamp(self._currently_playing["timestamp"] / 1000) @property def media_image_url(self) -> str | None: """Return the media image URL.""" if (self._currently_playing.get("item") is None or not self._currently_playing["item"]["album"]["images"]): return None return fetch_image_url(self._currently_playing["item"]["album"]) @property def media_title(self) -> str | None: """Return the media title.""" item = self._currently_playing.get("item") or {} return item.get("name") @property def media_artist(self) -> str | None: """Return the media artist.""" if self._currently_playing.get("item") is None: return None return ", ".join( artist["name"] for artist in self._currently_playing["item"]["artists"]) @property def media_album_name(self) -> str | None: """Return the media album.""" if self._currently_playing.get("item") is None: return None return self._currently_playing["item"]["album"]["name"] @property def media_track(self) -> int | None: """Track number of current playing media, music track only.""" item = self._currently_playing.get("item") or {} return item.get("track_number") @property def media_playlist(self): """Title of Playlist currently playing.""" if self._playlist is None: return None return self._playlist["name"] @property def source(self) -> str | None: """Return the current playback device.""" return self._currently_playing.get("device", {}).get("name") @property def source_list(self) -> list[str] | None: """Return a list of source devices.""" if not self._devices: return None return [device["name"] for device in self._devices] @property def shuffle(self) -> bool: """Shuffling state.""" return bool(self._currently_playing.get("shuffle_state")) @property def repeat(self) -> str | None: """Return current repeat mode.""" repeat_state = self._currently_playing.get("repeat_state") return REPEAT_MODE_MAPPING_TO_HA.get(repeat_state) @property def supported_features(self) -> int: """Return the media player features that are supported.""" if self._me["product"] != "premium": return 0 return SUPPORT_SPOTIFY @property def extra_state_attributes(self): """Return entity specific state attributes.""" return self._attributes @spotify_exception_handler def set_volume_level(self, volume: int) -> None: """Set the volume level.""" self._spotify.volume(int(volume * 100)) @spotify_exception_handler def media_play(self) -> None: """Start or resume playback.""" self._spotify.start_playback() @spotify_exception_handler def media_pause(self) -> None: """Pause playback.""" self._spotify.pause_playback() @spotify_exception_handler def media_previous_track(self) -> None: """Skip to previous track.""" self._spotify.previous_track() @spotify_exception_handler def media_next_track(self) -> None: """Skip to next track.""" self._spotify.next_track() @spotify_exception_handler def media_seek(self, position): """Send seek command.""" self._spotify.seek_track(int(position * 1000)) @spotify_exception_handler def play_media(self, media_type: str, media_id: str, **kwargs) -> None: """Play media.""" kwargs = {} # Spotify can't handle URI's with query strings or anchors # Yet, they do generate those types of URI in their official clients. media_id = str(URL(media_id).with_query(None).with_fragment(None)) self._attr_last_selected = media_id self._attributes[ATTR_LAST_SELECTED] = self._attr_last_selected self.update() if media_type in (MEDIA_TYPE_TRACK, MEDIA_TYPE_EPISODE, MEDIA_TYPE_MUSIC): kwargs["uris"] = [media_id] elif media_type in PLAYABLE_MEDIA_TYPES: kwargs["context_uri"] = media_id else: _LOGGER.error("Media type %s is not supported", media_type) return if not self._currently_playing.get("device") and self._devices: kwargs["device_id"] = self._devices[0].get("id") self._spotify.start_playback(**kwargs) self.update() @spotify_exception_handler def select_source(self, source: str) -> None: """Select playback device.""" for device in self._devices: if device["name"] == source: self._spotify.transfer_playback(device["id"], self.state == STATE_PLAYING) return @spotify_exception_handler def set_shuffle(self, shuffle: bool) -> None: """Enable/Disable shuffle mode.""" self._spotify.shuffle(shuffle) @spotify_exception_handler def set_repeat(self, repeat: str) -> None: """Set repeat mode.""" if repeat not in REPEAT_MODE_MAPPING_TO_SPOTIFY: raise ValueError(f"Unsupported repeat mode: {repeat}") self._spotify.repeat(REPEAT_MODE_MAPPING_TO_SPOTIFY[repeat]) @spotify_exception_handler def update(self) -> None: """Update state and attributes.""" self._attributes[ATTR_LAST_SELECTED] = self._attr_last_selected if not self.enabled: return if not self._session.valid_token or self._spotify is None: run_coroutine_threadsafe(self._session.async_ensure_token_valid(), self.hass.loop).result() self._spotify = Spotify(auth=self._session.token["access_token"]) current = self._spotify.current_playback() self._currently_playing = current or {} self._playlist = None context = self._currently_playing.get("context") if context is not None and context["type"] == MEDIA_TYPE_PLAYLIST: self._playlist = self._spotify.playlist(current["context"]["uri"]) devices = self._spotify.devices() or {} self._devices = devices.get("devices", []) async def async_browse_media(self, media_content_type=None, media_content_id=None): """Implement the websocket media browsing helper.""" if not self._scope_ok: _LOGGER.debug( "Spotify scopes are not set correctly, this can impact features such as media browsing" ) raise NotImplementedError if media_content_type in (None, "library"): return await self.hass.async_add_executor_job(library_payload) payload = { "media_content_type": media_content_type, "media_content_id": media_content_id, } response = await self.hass.async_add_executor_job( build_item_response, self._spotify, self._me, payload) if response is None: raise BrowseError( f"Media not found: {media_content_type} / {media_content_id}") return response
def main(): scope = "user-read-playback-state,user-modify-playback-state" sp = Spotify(client_credentials_manager=SpotifyClientCredentials(), auth_manager=SpotifyOAuth(scope=scope)) allchars = 'qwertyuiopasdfghjklzxcvbnm' market = "CA" # start with a canadian market (this will change later) while True: try: # normally get a ReadTimeoutError but I don't actually care what the error is - I just want it to power through until I stop it manually # initiate random query char = random.choice(allchars) n = 10000 offset = random.randint(0, n - 1) # random spot on the list try: results = sp.search( q='%' + char + '%', type='track', offset=offset, market=market ) # start a query with the letter somewhere in the middle - results ordered by popularity except: # most queries don't return n results continue # parse query result = results['tracks']['items'][ 0] # select the "first" song (offset by up to n) album_id = result['album']['id'] album_ = sp.album(album_id) markets = album_['available_markets'] market = random.choice(markets) # choose new market artists = result['artists'] # filter if result['explicit']: # skip explicit continue skip_artist = False for artist in artists: if artist['name'] in [ 'Daddy Yankee', 'J Balvin', 'Don Omar', 'Bad Bunny', 'KAROL G', 'Wisin & Yandel' ]: # skip reggaeton skip_artist = True break if skip_artist: continue # play track sp.start_playback(uris=['spotify:track:' + result['id'] ]) # play track sleep(0.5) # wait for track to start pprint(result) # simplest event listener while True: # start next track when current one finishes while True: if sp.current_playback( )['progress_ms']: # playback started break sleep(0.1) # don't consume too much CPU while True: if not sp.current_playback( )['progress_ms']: # playback stopped # Triggers at end of track (a simple method for which I didn't find) # Doesn't trigger if paused as long as progress is nonzero # In theory, can trigger if track is set back to start while playing (progress = 0), but unlikely since the intepreter only checks this condition every 100 milliseconds or so, while the track begins to play much more quickly than that (making nonzero progress) # DOES trigger if track is set back to zero while paused break sleep(0.1) # don't consume too much CPU break print('Changing track') except Exception as e: print(e) continue # send the interpreter back to the top of the loop to ensure the current track keeps playing
from spotipy import Spotify from spotipy.oauth2 import SpotifyPKCE import asyncio, websockets, time, ast import platform, subprocess auth_manager = SpotifyPKCE(client_id="a9ed7f99384943dc98518ed396cd639a", redirect_uri="http://localhost:7998/callback", scope="streaming user-read-playback-state user-modify-playback-state") sp = Spotify(auth_manager=auth_manager) device_id = sp.current_playback()['device']['id'] def play(uris: str): sp.start_playback(uris=uris, device_id=device_id) sp.repeat("context") sp.shuffle(False) def pause(): sp.pause_playback() def print_track(track): if platform.system() == "Windows": subprocess.run("cls", shell=True) else: subprocess.run("clear", shell=True) print("Now playing:")
class SpotifyWidget(QWidget): """Spotify application. It displays the cover image, the artist name and song name.""" display_name = "Spotify" def __init__(self, main_window: "InfoPad") -> None: super().__init__() self.main_window = main_window loadUi(f"{self.main_window.current_path}/widgets/spotify/spotify.ui", self) self.track_icon.setScaledContents(True) @staticmethod def get_icon(curr_path: str) -> QPixmap: """Icon made by Pixel perfect from www.flaticon.com""" return QPixmap(f"{curr_path}/widgets/spotify/spotify.png") def on_enter(self) -> None: """Read client_id, client_secret, and redirect_uri from credentials.cfg. It will then create a spotipy instance and retrieve cover image, artist name, and song name from current playing song. """ self.credentials = ConfigParser() self.credentials.read(f"{self.main_window.current_path}/credentials.cfg") client_id = self.credentials["SPOTIPY"]["CLIENT_ID"] client_secret = self.credentials["SPOTIPY"]["CLIENT_SECRET"] redirect_uri = self.credentials["SPOTIPY"]["REDIRECT_URI"] scope = "user-read-playback-state" self.sp = Spotify( client_credentials_manager=SpotifyOAuth( client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, cache_path=f"{self.main_window.current_path}/.cache", scope=scope, ) ) self.res = self.sp.current_playback() if self.res: if self.res["item"]["album"]["images"]: largest_img = self.res["item"]["album"]["images"][0]["url"] self.image = requests.get(largest_img).content self.image_pixmap = QPixmap() self.image_pixmap.loadFromData(self.image) self.track_icon.setPixmap(self.image_pixmap) else: self.image = None self.image_pixmap = QPixmap( f"{self.main_window.current_path}/widgets/spotify/no_image.png" ) self.track_icon.setPixmap(self.image_pixmap) song_name = self.res["item"]["name"] artist = self.res["item"]["artists"][0]["name"] self.track_artist.setText(artist) self.track_song.setText(song_name) else: self.image = None self.image_pixmap = QPixmap( f"{self.main_window.current_path}/widgets/spotify/no_image.png" ) self.track_icon.setPixmap(self.image_pixmap) self.track_artist.setText("Nothing playing") self.track_song.setText("Nothing playing") def on_exit(self) -> None: """Clear labels and delete variables in order to save memory""" self.track_icon.clear() self.track_artist.clear() self.track_song.clear() if self.res: del self.image del self.image_pixmap del self.credentials del self.res del self.sp def grid_1(self) -> None: pass # Num 4 def grid_2(self) -> None: pass # Num 5 def grid_3(self) -> None: pass # Num 6 def grid_4(self) -> None: pass # Num + def grid_5(self) -> None: pass # Num 1 def grid_6(self) -> None: pass # Num 2 def grid_7(self) -> None: pass # Num 3 def grid_8(self) -> None: pass # Num Enter def grid_9(self) -> None: pass # Num 9 def grid_sd(self) -> None: pass # Num 7 def grid_su(self) -> None: pass # Num 8 def grid_view_o(self) -> None: pass # Num Page Down
def current_playback(player: spotipy.Spotify): return player.current_playback()