mirror of
https://github.com/KevinMidboe/spotify-downloader.git
synced 2025-10-29 18:00:15 +00:00
Authenticating services
This commit is contained in:
7
setup.py
7
setup.py
@@ -16,8 +16,11 @@ setup(
|
|||||||
"spotdl.lyrics.providers",
|
"spotdl.lyrics.providers",
|
||||||
"spotdl.encode",
|
"spotdl.encode",
|
||||||
"spotdl.encode.encoders",
|
"spotdl.encode.encoders",
|
||||||
"spotdl.downloaders",
|
"spotdl.metadata",
|
||||||
"spotdl.patch",
|
"spotdl.metadata.embedders",
|
||||||
|
"spotdl.metadata.providers",
|
||||||
|
"spotdl.authorize",
|
||||||
|
"spotdl.authorize.services",
|
||||||
],
|
],
|
||||||
version=spotdl.__version__,
|
version=spotdl.__version__,
|
||||||
install_requires=[
|
install_requires=[
|
||||||
|
|||||||
6
spotdl/authorize/__init__.py
Normal file
6
spotdl/authorize/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
from spotdl.authorize.authorize_base import AuthorizeBase
|
||||||
|
|
||||||
|
from spotdl.authorize.exceptions import AuthorizationError
|
||||||
|
from spotdl.authorize.exceptions import SpotifyAuthorizationError
|
||||||
|
from spotdl.authorize.exceptions import YouTubeAuthorizationError
|
||||||
|
|
||||||
19
spotdl/authorize/authorize_base.py
Normal file
19
spotdl/authorize/authorize_base.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from abc import ABC
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
class AuthorizeBase(ABC):
|
||||||
|
"""
|
||||||
|
Defined service authenticators must inherit from this abstract
|
||||||
|
base class and implement their own functionality for the below
|
||||||
|
defined methods.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def authorize(self):
|
||||||
|
"""
|
||||||
|
This method must authorize with the corresponding service
|
||||||
|
and return an object that can be utilized in making
|
||||||
|
authenticated requests.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
20
spotdl/authorize/exceptions.py
Normal file
20
spotdl/authorize/exceptions.py
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
class AuthorizationError(Exception):
|
||||||
|
__module__ = Exception.__module__
|
||||||
|
|
||||||
|
def __init__(self, message=None):
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class SpotifyAuthorizationError(AuthorizationError):
|
||||||
|
__module__ = Exception.__module__
|
||||||
|
|
||||||
|
def __init__(self, message=None):
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class YouTubeAuthorizationError(AuthorizationError):
|
||||||
|
__module__ = Exception.__module__
|
||||||
|
|
||||||
|
def __init__(self, message=None):
|
||||||
|
super().__init__(message)
|
||||||
|
|
||||||
2
spotdl/authorize/services/__init__.py
Normal file
2
spotdl/authorize/services/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
from spotdl.authorize.services.spotify import AuthorizeSpotify
|
||||||
|
|
||||||
55
spotdl/authorize/services/spotify.py
Normal file
55
spotdl/authorize/services/spotify.py
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
from spotdl.authorize import AuthorizeBase
|
||||||
|
from spotdl.authorize.exceptions import SpotifyAuthorizationError
|
||||||
|
|
||||||
|
import spotipy
|
||||||
|
import spotipy.oauth2 as oauth2
|
||||||
|
|
||||||
|
# This global_client is used to keep the last logged-in client
|
||||||
|
# object in memory for for persistence. If credentials aren't
|
||||||
|
# provided when creating further objects, the last authenticated
|
||||||
|
# client object with correct credentials is returned when
|
||||||
|
# `AuthorizeSpotify().authorize()` is called.
|
||||||
|
global_client = None
|
||||||
|
|
||||||
|
class AuthorizeSpotify(AuthorizeBase):
|
||||||
|
def __init__(self):
|
||||||
|
global global_client
|
||||||
|
self._client = global_client
|
||||||
|
|
||||||
|
def _generate_token(self, client_id, client_secret):
|
||||||
|
""" Generate the token. """
|
||||||
|
credentials = oauth2.SpotifyClientCredentials(
|
||||||
|
client_id=client_id,
|
||||||
|
client_secret=client_secret,
|
||||||
|
)
|
||||||
|
token = credentials.get_access_token()
|
||||||
|
return token
|
||||||
|
|
||||||
|
def authorize(self, client_id=None, client_secret=None):
|
||||||
|
no_credentials_provided = client_id is None and client_secret is None
|
||||||
|
not_valid_input = no_credentials_provided and self._client is None
|
||||||
|
|
||||||
|
if not_valid_input:
|
||||||
|
raise SpotifyAuthorizationError(
|
||||||
|
"You must pass in client_id and client_secret to this method "
|
||||||
|
"when authenticating for the first time."
|
||||||
|
)
|
||||||
|
|
||||||
|
if no_credentials_provided:
|
||||||
|
return self._client
|
||||||
|
|
||||||
|
try:
|
||||||
|
token = self._generate_token(client_id, client_secret)
|
||||||
|
except spotipy.SpotifyOauthError:
|
||||||
|
raise SpotifyAuthorizeError(
|
||||||
|
"Failed to retrieve token. Perhaps you provided invalid credentials?"
|
||||||
|
)
|
||||||
|
|
||||||
|
spotify = spotipy.Spotify(auth=token)
|
||||||
|
|
||||||
|
self._client = spotify
|
||||||
|
global global_client
|
||||||
|
global_client = spotify
|
||||||
|
|
||||||
|
return spotify
|
||||||
|
|
||||||
19
spotdl/authorize/services/tests/test_spotify.py
Normal file
19
spotdl/authorize/services/tests/test_spotify.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
from spotdl.authorize.services import AuthorizeSpotify
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
class TestSpotifyAuthorize:
|
||||||
|
# TODO: Test these once we a have config.py
|
||||||
|
# storing pre-defined default credentials.
|
||||||
|
#
|
||||||
|
# We'll use these credentials to create
|
||||||
|
# a spotipy object via below tests
|
||||||
|
|
||||||
|
@pytest.mark.xfail
|
||||||
|
def test_generate_token(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
@pytest.mark.xfail
|
||||||
|
def test_authorize(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
16
spotdl/authorize/tests/test_authorize_base.py
Normal file
16
spotdl/authorize/tests/test_authorize_base.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
from spotdl.authorize import AuthorizeBase
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
class TestAbstractBaseClass:
|
||||||
|
def test_error_abstract_base_class_authorizebase(self):
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
AuthorizeBase()
|
||||||
|
|
||||||
|
def test_inherit_abstract_base_class_authorizebase(self):
|
||||||
|
class AuthorizeKid(AuthorizeBase):
|
||||||
|
def authorize(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
AuthorizeKid()
|
||||||
|
|
||||||
15
spotdl/authorize/tests/test_authorize_exceptions.py
Normal file
15
spotdl/authorize/tests/test_authorize_exceptions.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from spotdl.authorize.exceptions import AuthorizationError
|
||||||
|
from spotdl.authorize.exceptions import SpotifyAuthorizationError
|
||||||
|
from spotdl.authorize.exceptions import YouTubeAuthorizationError
|
||||||
|
|
||||||
|
|
||||||
|
class TestEncoderNotFoundSubclass:
|
||||||
|
def test_authozation_error_subclass(self):
|
||||||
|
assert issubclass(AuthorizationError, Exception)
|
||||||
|
|
||||||
|
def test_spotify_authorization_error_subclass(self):
|
||||||
|
assert issubclass(SpotifyAuthorizationError, AuthorizationError)
|
||||||
|
|
||||||
|
def test_youtube_authorization_error_subclass(self):
|
||||||
|
assert issubclass(YouTubeAuthorizationError, AuthorizationError)
|
||||||
|
|
||||||
@@ -17,16 +17,6 @@ from spotdl.lyrics.exceptions import LyricsNotFoundError
|
|||||||
spotify = None
|
spotify = None
|
||||||
|
|
||||||
|
|
||||||
def generate_token():
|
|
||||||
""" Generate the token. """
|
|
||||||
credentials = oauth2.SpotifyClientCredentials(
|
|
||||||
client_id=const.args.spotify_client_id,
|
|
||||||
client_secret=const.args.spotify_client_secret,
|
|
||||||
)
|
|
||||||
token = credentials.get_access_token()
|
|
||||||
return token
|
|
||||||
|
|
||||||
|
|
||||||
def must_be_authorized(func, spotify=spotify):
|
def must_be_authorized(func, spotify=spotify):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
global spotify
|
global spotify
|
||||||
|
|||||||
Reference in New Issue
Block a user