save login

This commit is contained in:
Zotify 2024-09-18 18:08:18 +12:00
parent 66e98dc98d
commit b11ecfa61a
5 changed files with 49 additions and 47 deletions

View File

@ -10,6 +10,7 @@
### Changes ### Changes
- Username and password login has been replaced with username and token
- Genre metadata available for all tracks - Genre metadata available for all tracks
- Boolean command line options are now set like `--save-metadata` or `--no-save-metadata` for True or False - Boolean command line options are now set like `--save-metadata` or `--no-save-metadata` for True or False
- Setting `--config` (formerly `--config-location`) can be set to "None" to not use any config file - Setting `--config` (formerly `--config-location`) can be set to "None" to not use any config file

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = zotify name = zotify
version = 0.9.6 version = 0.9.7
author = Zotify Contributors author = Zotify Contributors
description = A highly customizable music and podcast downloader description = A highly customizable music and podcast downloader
long_description = file: README.md long_description = file: README.md

View File

@ -70,8 +70,8 @@ class Session(LibrespotSession):
def __init__( def __init__(
self, self,
session_builder: LibrespotSession.Builder, session_builder: LibrespotSession.Builder,
oauth: OAuth,
language: str = "en", language: str = "en",
oauth: OAuth | None = None,
) -> None: ) -> None:
""" """
Authenticates user, saves credentials to a file and generates api token. Authenticates user, saves credentials to a file and generates api token.
@ -96,7 +96,7 @@ class Session(LibrespotSession):
self.authenticate(session_builder.login_credentials) self.authenticate(session_builder.login_credentials)
@staticmethod @staticmethod
def from_file(auth: OAuth, cred_file: Path | str, language: str = "en") -> Session: def from_file(cred_file: Path | str, language: str = "en") -> Session:
""" """
Creates session using saved credentials file Creates session using saved credentials file
Args: Args:
@ -107,17 +107,17 @@ class Session(LibrespotSession):
""" """
if not isinstance(cred_file, Path): if not isinstance(cred_file, Path):
cred_file = Path(cred_file).expanduser() cred_file = Path(cred_file).expanduser()
conf = ( config = (
LibrespotSession.Configuration.Builder() LibrespotSession.Configuration.Builder()
.set_store_credentials(False) .set_store_credentials(False)
.build() .build()
) )
session = LibrespotSession.Builder(conf).stored_file(str(cred_file)) session = LibrespotSession.Builder(config).stored_file(str(cred_file))
return Session(session, auth, language) # TODO return Session(session, language)
@staticmethod @staticmethod
def from_oauth( def from_oauth(
auth: OAuth, oauth: OAuth,
save_file: Path | str | None = None, save_file: Path | str | None = None,
language: str = "en", language: str = "en",
) -> Session: ) -> Session:
@ -129,24 +129,24 @@ class Session(LibrespotSession):
Returns: Returns:
Zotify session Zotify session
""" """
builder = LibrespotSession.Configuration.Builder() config = LibrespotSession.Configuration.Builder()
if save_file: if save_file:
if not isinstance(save_file, Path): if not isinstance(save_file, Path):
save_file = Path(save_file).expanduser() save_file = Path(save_file).expanduser()
save_file.parent.mkdir(parents=True, exist_ok=True) save_file.parent.mkdir(parents=True, exist_ok=True)
builder.set_stored_credential_file(str(save_file)) config.set_stored_credential_file(str(save_file))
else: else:
builder.set_store_credentials(False) config.set_store_credentials(False)
token = auth.await_token() token = oauth.await_token()
session = LibrespotSession.Builder(builder.build()) builder = LibrespotSession.Builder(config.build())
session.login_credentials = Authentication.LoginCredentials( builder.login_credentials = Authentication.LoginCredentials(
username=auth.username, username=oauth.username,
typ=Authentication.AuthenticationType.values()[3], typ=Authentication.AuthenticationType.values()[3],
auth_data=token.access_token.encode(), auth_data=token.access_token.encode(),
) )
return Session(session, auth, language) return Session(builder, language, oauth)
def __get_playable( def __get_playable(
self, playable_id: PlayableId, quality: Quality self, playable_id: PlayableId, quality: Quality
@ -186,7 +186,7 @@ class Session(LibrespotSession):
self.api(), self.api(),
) )
def oauth(self) -> OAuth: def oauth(self) -> OAuth | None:
"""Returns OAuth service""" """Returns OAuth service"""
return self.__oauth return self.__oauth
@ -282,7 +282,10 @@ class TokenProvider(LibrespotTokenProvider):
self._session = session self._session = session
def get_token(self, *scopes) -> TokenProvider.StoredToken: def get_token(self, *scopes) -> TokenProvider.StoredToken:
return self._session.oauth().get_token() oauth = self._session.oauth()
if oauth is None:
return super().get_token(*scopes)
return oauth.get_token()
class StoredToken(LibrespotTokenProvider.StoredToken): class StoredToken(LibrespotTokenProvider.StoredToken):
def __init__(self, obj): def __init__(self, obj):
@ -301,15 +304,15 @@ class OAuth:
def __init__(self, username: str): def __init__(self, username: str):
self.username = username self.username = username
self.__server_thread = Thread(target=self.__run_server)
self.__server_thread.start()
def get_authorization_url(self) -> str: def auth_interactive(self) -> str:
""" """
Generate OAuth URL Starts local server for token callback
Returns: Returns:
OAuth URL OAuth URL
""" """
self.__server_thread = Thread(target=self.__run_server)
self.__server_thread.start()
self.__code_verifier = generate_code_verifier() self.__code_verifier = generate_code_verifier()
code_challenge = get_code_challenge(self.__code_verifier) code_challenge = get_code_challenge(self.__code_verifier)
params = { params = {

View File

@ -7,7 +7,7 @@ from zotify.app import App
from zotify.config import CONFIG_PATHS, CONFIG_VALUES from zotify.config import CONFIG_PATHS, CONFIG_VALUES
from zotify.utils import OptionalOrFalse from zotify.utils import OptionalOrFalse
VERSION = "0.9.6" VERSION = "0.9.7"
def main(): def main():
@ -51,7 +51,7 @@ def main():
help="Searches for only this type", help="Searches for only this type",
) )
parser.add_argument("--username", type=str, default="", help="Account username") parser.add_argument("--username", type=str, default="", help="Account username")
parser.add_argument("--password", type=str, default="", help="Account password") parser.add_argument("--token", type=str, default="", help="Account token")
group = parser.add_mutually_exclusive_group(required=True) group = parser.add_mutually_exclusive_group(required=True)
group.add_argument( group.add_argument(
"urls", "urls",
@ -127,8 +127,7 @@ def main():
args = parser.parse_args() args = parser.parse_args()
if args.version: if args.version:
print(VERSION) print(VERSION)
return elif args.debug:
if args.debug:
args.func(args) args.func(args)
else: else:
try: try:

View File

@ -149,27 +149,26 @@ class App:
Logger(self.__config) Logger(self.__config)
# Create session # Create session
# if args.username != "" and args.password != "": if args.username != "" and args.token != "":
# self.__session = Session.from_userpass( oauth = OAuth(args.username)
# args.username, oauth.set_token(args.token, OAuth.RequestType.REFRESH)
# args.password, self.__session = Session.from_oauth(
# self.__config.credentials_path, oauth, self.__config.credentials_path, self.__config.language
# self.__config.language, )
# ) elif self.__config.credentials_path.is_file():
# elif self.__config.credentials_path.is_file(): self.__session = Session.from_file(
# self.__session = Session.from_file( self.__config.credentials_path,
# self.__config.credentials_path, self.__config.language self.__config.language,
# ) )
# else: else:
# self.__session = Session.from_prompt( username = args.username
# self.__config.credentials_path, self.__config.language while username == "":
# )
username = input("Username: ") username = input("Username: ")
auth = OAuth(username) oauth = OAuth(username)
auth_url = auth.get_authorization_url() auth_url = oauth.auth_interactive()
print(f"\nClick on the following link to login:\n{auth_url}") print(f"\nClick on the following link to login:\n{auth_url}")
self.__session = Session.from_oauth( self.__session = Session.from_oauth(
auth, self.__config.credentials_path, self.__config.language oauth, self.__config.credentials_path, self.__config.language
) )
# Get items to download # Get items to download