Skip to content

Commit

Permalink
fix for #2
Browse files Browse the repository at this point in the history
and other tweaks
  • Loading branch information
s4w3d0ff authored Feb 3, 2025
1 parent 4f7f449 commit 2482ffa
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 24 deletions.
4 changes: 2 additions & 2 deletions spotifio/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ async def _check_scope(self, method_name):
if missing_scopes:
raise Exception(f"Missing required scopes for {method_name}: {', '.join(missing_scopes)}")

async def login(self):
async def login(self, token=None):
""" Sets up the token """
await self.token_handler._login()
await self.token_handler._login(token)

async def _request(self, method, endpoint, params=None, data=None, headers=None):
""" Base Request Method for Spotify API calls """
Expand Down
44 changes: 22 additions & 22 deletions spotifio/oauth.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import aiohttp
import asyncio
import webbrowser
import random
import os
import base64
import logging
import time
Expand All @@ -24,14 +24,6 @@
</html>
"""


def randString(length=12, chars=None):
if not chars:
import string
chars = string.ascii_letters + string.digits
ranstr = ''.join(random.choice(chars) for _ in range(length))
return ranstr

class WebServer:
def __init__(self, host, port):
self.app = web.Application()
Expand Down Expand Up @@ -68,7 +60,7 @@ def __init__(self, client_id, client_secret, redirect_uri=None, scope=[], storag
self.redirect_uri = redirect_uri or "http://localhost:8888/callback"
self.scope = scope
self.storage = storage or JSONStorage()
self._state = randString(16)
self._state = os.urandom(14).hex()
self._auth_code = None
self._auth_future = None
self._token = None
Expand Down Expand Up @@ -96,7 +88,7 @@ async def _callback_handler(self, request):
return web.Response(text=closeBrowser, content_type='text/html', charset='utf-8')

async def _get_auth_code(self):
logger.warning(f"Getting Oauth code...")
logger.warning(f"Opening browser to get Oauth code...")
await self.server.start()
self._auth_future = asyncio.Future()
params = {
Expand All @@ -107,12 +99,18 @@ async def _get_auth_code(self):
}
if self.scope:
params['scope'] = ' '.join(self.scope)
# open webbrowser with auth link
webbrowser.open(f"https://accounts.spotify.com/authorize?{urlencode(params)}")
auth_link = f"https://accounts.spotify.com/authorize?{urlencode(params)}"
try:
# open webbrowser with auth link
webbrowser.open(auth_link)
except:
# cant open webbrowser, show auth link for user to copy/paste
logger.error(f"Couldn't open default browser!: \n{auth_link}")
# wait for auth code
await self._auth_future
# stop webserver
await self.server.stop()
logger.warning(f"Got Oauth code!")

async def _token_request(self, data):
""" Base token request method, used for new or refreshing tokens """
Expand Down Expand Up @@ -144,8 +142,8 @@ async def _refresh_token(self):

async def _get_new_token(self):
""" Get a new oauth token using the oauth code, get code if we dont have one yet """
logger.warning(f"Getting new token...")
await self._get_auth_code()
logger.warning(f"Getting new token...")
return await self._token_request({
"grant_type": "authorization_code",
"code": self._auth_code,
Expand All @@ -156,29 +154,31 @@ async def _token_refresher(self):
""" Waits for the time to refresh the token and refreshes """
self._running = True
self._refresh_event.set()
logger.debug(f"_token_refresher started...")
while self._running:
time_left = self._token['expires_time'] - time.time()
logger.info(f"Token expires in {time_left} seconds...")
if time_left <= 0:
logger.debug(f"Token expires in {time_left} seconds...")
if time_left-60 <= 0:
# pause 'self.get_token'
self._refresh_event.clear()
# refresh token
await self._refresh_token()
# resume 'self.get_token'
self._refresh_event.set()
continue # skip sleep to get new time_left
await asyncio.sleep(time_left+0.5)
await asyncio.sleep(time_left-60)

async def _login(self, token=None):
""" Checks storage for saved token, gets new token if one isnt found. Starts the token refresher task."""
self._token = token
self._refresh_task = None
if not self._token:
logger.warning(f"Attempting to load saved token...")
self._refresh_task = None
logger.debug(f"Attempting to load saved token...")
self._token = await self.storage.load_token(name="spotify")
if not self._token:
logger.warning(f"No token found in storage!")
self._token = await self._get_new_token()
if self._token:
logger.warning(f"Loaded saved token from storage!")
else:
self._token = await self._get_new_token()
self._refresh_task = asyncio.create_task(self._token_refresher())

async def get_token(self):
Expand Down

0 comments on commit 2482ffa

Please sign in to comment.