Esempio n. 1
0
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'})
Esempio n. 2
0
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}"
        )
Esempio n. 3
0
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'])
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 7
0
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
Esempio n. 8
0
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:")
Esempio n. 9
0
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
Esempio n. 10
0
def current_playback(player: spotipy.Spotify):
    return player.current_playback()