Beispiel #1
0
    def _get_authorization_token(self, cache_token=True) -> str:
        """ Step 2
        """

        logger.info('Get authorization token')

        code_verifier, code_challenge = self._generate_consts()

        data = {
            'client_id': self.client_id,
            'grant_type': 'authorization_code',
            'code': self._get_authorization_code(code_challenge),
            'redirect_uri': self.redirect_uri,
            'code_verifier': code_verifier
        }

        resp = self._session.post(url=self.AUTH_TOKEN_URL, data=data)
        if resp.status_code != 200:
            result = resp.json()
            logger.error('Getting responce token error')
            raise AuthFlowRequestError(error=result['error'],
                                       error_descr=result['error_description'],
                                       code=resp.status_code)

        self.token_info = resp.json()
        self.token_info['expires_at'] = int(
            time.time()) + self.token_info["expires_in"]

        if cache_token:
            self._cache_token()
Beispiel #2
0
    def _refresh_authorization_token(self, cache_token=True) -> None:
        """ Requesting a refreshed access token; Spotify returns a new access token to your app
        """

        logger.info('Refresh expired token')
        headers = self._make_authorization_headers(self._client_id,
                                                   self._client_secret)

        data = {
            'grant_type': 'refresh_token',
            'refresh_token': self.token_info['refresh_token'],
            'redirect_uri': self.redirect_uri
        }

        resp = self._session.post(url=self.AUTH_TOKEN_URL,
                                  headers=headers,
                                  data=data)
        if resp.status_code != 200:
            result = resp.json()
            logger.error('Getting responce token error')
            raise AuthFlowRequestError(error=result['error'],
                                       error_descr=result['error_description'],
                                       code=resp.status_code)
        logger.debug(resp.text)
        self.token_info = resp.json()
        self.token_info['expires_at'] = int(
            time.time()) + self.token_info["expires_in"]
        if cache_token:
            self._cache_token()
Beispiel #3
0
    def getUserCurrentPlayback(self):
        # logger.debug(f'Getting current playback')

        try:
            res = self.__api_request(method='GET', url_path='me/player')
            res.raise_for_status()
        except SpotifyRequestError as err:
            logger.error(err)
            raise
        if res.status_code == 204:
            raise SpotifyRequestNoContent
        return res.json()
Beispiel #4
0
    def _get_authorization_token(self, cache_token=True) -> None:
        """ Step 2. Exchange code with an access token

        POST https://accounts.spotify.com/api/token

        The body must contain the following parameters encoded in application/x-www-form-urlencoded as defined in the OAuth 2.0 specification:

        POST data: grant_type=authorization_code, code, redirect_uri
        Headers: Base 64 encoded string that contains the client ID and client secret key. The field must have the format: "Authorization: Basic *<base64 encoded client_id:client_secret>*"

        Return:
        - access_token
        - token_type=“Bearer”
        - scope -- space-separated list of scopes which have been granted for this access_token
        - expires_in -- The time period (in seconds) for which the access token is valid
        - refresh_token -- a token that can be sent to the Spotify Accounts service in place of an authorization code.
          When the access code expires, send a POST request to the Accounts service /api/token endpoint,
          but use this code in place of an authorization code. A new access token will be returned.
          A new refresh token might be returned too.)
        """

        logger.info('Get authorization token')

        headers = self._make_authorization_headers(self._client_id,
                                                   self._client_secret)

        data = {
            'grant_type': 'authorization_code',
            'code': self._get_authorization_code(),
            'redirect_uri': self.redirect_uri
        }

        resp = self._session.post(url=self.AUTH_TOKEN_URL,
                                  headers=headers,
                                  data=data)
        if resp.status_code != 200:
            result = resp.json()
            logger.error('Getting responce token error')
            raise AuthFlowRequestError(error=result['error'],
                                       error_descr=result['error_description'],
                                       code=resp.status_code)
        self.token_info = resp.json(
        )  # {'access_token': 'BQ...', 'token_type': 'Bearer', 'expires_in': 3600, 'refresh_token': 'AQ...', 'scope': '...'}
        self.token_info['expires_at'] = int(
            time.time()) + self.token_info["expires_in"]

        if cache_token:
            self._cache_token()
Beispiel #5
0
    def search(self,
               raw_q,
               q_type,
               market=None,
               limit=None,
               offset=None,
               include_external=False):
        """ Search for an Item

        raw_q:   String with operators and flters:
                 q='album:arrival artist:abba'
                 q="doom metal"

        q_type:  String with one of many types
                 Example: q_type=album, q_type=album,track

        Returns: 
        For each type provided in the type parameter, the response body contains an array of artist objects / simplified album objects / track objects / simplified show objects / simplified episode objects wrapped in a paging object in JSON.
        """

        avaliable_types = [
            'album', 'artist', 'playlist', 'track', 'show', 'episode'
        ]

        if q_type not in avaliable_types:
            raise SpotifyError(
                f'"q_type" must be {", ".join([x for x in avaliable_types])}')

        payload = {'q': raw_q, 'type': q_type}

        if market:
            payload.update({'market': market})
        if limit:
            payload.update({'limit': limit})
        if include_external:
            payload.update({'locale': include_external})
        if offset:
            payload.update({'offset': offset})

        try:
            resp = self.__api_request(method='GET',
                                      url_path='search',
                                      params=payload)
            resp.raise_for_status()
        except SpotifyRequestError as err:
            logger.error(err)
            raise
        return resp.json()
Beispiel #6
0
    def startOrResumeUserPlayback(self,
                                  device_id=None,
                                  context_uri=None,
                                  uris=None,
                                  offset=None,
                                  position_ms=None):
        """ user-modify-playback-state

        context_uri:    Spotify URI of the context to play (albums, artists, playlists).
                        Example: {"context_uri": "spotify:album:1Je1IMUlBXcx1Fz0WE7oPT"}
        uris:    Spotify track URIs to play.
                 Example: {"uris": ["spotify:track:4iV5W9uYEdYUVa79Axb7Rh", "spotify:track:1301WleyT98MSxVHPZCA6M"]}
        offset:    Indicates from where in the context playback should start.
                   Avaliable when `context_uri` corresponds to an album or playlist object, or when the `uris` parameter is used.
                   Example: "offset": {"position": 5}
                   “uri” is a string representing the uri of the item to start at.
                   Example: "offset": {"uri": "spotify:track:1301WleyT98MSxVHPZCA6M"}
        position_ms:    Passing in a position that is greater than the length of the track will cause the player to start playing the next song.
        """
        # logger.debug(f"Start/Resume a User's Playback")
        params = dict()
        if device_id:
            params.update({"device_id": device_id})
        body = dict()
        if context_uri:
            body.update({"context_uri": context_uri})
        if uris:
            body.update({"uris": uris})
        if offset:
            body.update({"offset": offset})
        if position_ms:
            body.update({"position_ms": position_ms})

        if not body:
            body = {}

        try:
            res = self.__api_request(method='PUT',
                                     url_path='me/player/play',
                                     params=params,
                                     data=json.dumps(body))
        except SpotifyRequestError as err:
            logger.error(err)
            raise
        return res
Beispiel #7
0
    def getUserCurrentTrack(self, market=None):
        """ Get the object currently being played on the user’s Spotify account."""
        # logger.debug(f"Get the User's Currently Playing Track")

        query = None

        if market:
            query = {'market': market}

        try:
            res = self.__api_request(method='GET',
                                     url_path='me/player/currently-playing',
                                     params=query)
        except SpotifyRequestError as err:
            logger.error(err)
            raise
        if res.status_code == 204:
            raise SpotifyRequestNoContent
        return res.json()
Beispiel #8
0
    def __api_request(self,
                      method,
                      url_path,
                      headers=None,
                      params=None,
                      data=None):
        headers = self._get_headers()
        url = urljoin(self.SPOTIFY_API_URL, url_path)

        try:
            resp = self._session.request(method=method,
                                         url=url,
                                         headers=headers,
                                         params=params,
                                         data=data)
            resp.raise_for_status()
        except requests.exceptions.HTTPError as err:
            logger.error(err)
            raise SpotifyRequestError(resp.text)

        return resp