1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798 |
- import os
- import os.path
- from getpass import getpass
- import time
- import requests
- from librespot.audio.decoders import VorbisOnlyAudioQuality
- from librespot.core import Session
- from const import TYPE, \
- PREMIUM, USER_READ_EMAIL, OFFSET, LIMIT, \
- PLAYLIST_READ_PRIVATE, USER_LIBRARY_READ
- from config import Config
- class ZSpotify:
- SESSION: Session = None
- DOWNLOAD_QUALITY = None
- CONFIG: Config = Config()
- def __init__(self, args):
- ZSpotify.CONFIG.load(args)
- ZSpotify.login()
- @classmethod
- def login(cls):
- """ Authenticates with Spotify and saves credentials to a file """
- cred_location = Config.get_credentials_location()
- if os.path.isfile(cred_location):
- try:
- cls.SESSION = Session.Builder().stored_file(cred_location).create()
- return
- except RuntimeError:
- pass
- while True:
- user_name = ''
- while len(user_name) == 0:
- user_name = input('Username: ')
- password = getpass()
- try:
- conf = Session.Configuration.Builder().set_stored_credential_file(cred_location).build()
- cls.SESSION = Session.Builder(conf).user_pass(user_name, password).create()
- return
- except RuntimeError:
- pass
- @classmethod
- def get_content_stream(cls, content_id, quality):
- return cls.SESSION.content_feeder().load(content_id, VorbisOnlyAudioQuality(quality), False, None)
- @classmethod
- def __get_auth_token(cls):
- return cls.SESSION.tokens().get_token(USER_READ_EMAIL, PLAYLIST_READ_PRIVATE, USER_LIBRARY_READ).access_token
- @classmethod
- def get_auth_header(cls):
- return {
- 'Authorization': f'Bearer {cls.__get_auth_token()}',
- 'Accept-Language': f'{cls.CONFIG.get_language()}'
- }
- @classmethod
- def get_auth_header_and_params(cls, limit, offset):
- return {
- 'Authorization': f'Bearer {cls.__get_auth_token()}',
- 'Accept-Language': f'{cls.CONFIG.get_language()}'
- }, {LIMIT: limit, OFFSET: offset}
- @classmethod
- def invoke_url_with_params(cls, url, limit, offset, **kwargs):
- headers, params = cls.get_auth_header_and_params(limit=limit, offset=offset)
- params.update(kwargs)
- return requests.get(url, headers=headers, params=params).json()
- @classmethod
- def invoke_url(cls, url, tryCount=0):
- # we need to import that here, otherwise we will get circular imports!
- from termoutput import Printer, PrintChannel
- headers = cls.get_auth_header()
- response = requests.get(url, headers=headers)
- responsetext = response.text
- responsejson = response.json()
- if 'error' in responsejson:
- if tryCount < (cls.CONFIG.get_retry_attempts() - 1):
- Printer.print(PrintChannel.WARNINGS, f"Spotify API Error (try {tryCount + 1}) ({responsejson['error']['status']}): {responsejson['error']['message']}")
- time.sleep(5)
- return cls.invoke_url(url, tryCount + 1)
- Printer.print(PrintChannel.API_ERRORS, f"Spotify API Error ({responsejson['error']['status']}): {responsejson['error']['message']}")
- return responsetext, responsejson
- @classmethod
- def check_premium(cls) -> bool:
- """ If user has spotify premium return true """
- return (cls.SESSION.get_user_attribute(TYPE) == PREMIUM) or cls.CONFIG.get_force_premium()
|