added get authed network function to reduce token refreshing, added play endpoint
This commit is contained in:
parent
215c839210
commit
d0adcc679b
@ -13,6 +13,10 @@ from werkzeug.security import check_password_hash, generate_password_hash
|
|||||||
|
|
||||||
from spotify.tasks.run_user_playlist import run_user_playlist as run_user_playlist
|
from spotify.tasks.run_user_playlist import run_user_playlist as run_user_playlist
|
||||||
from spotify.tasks.play_user_playlist import play_user_playlist as play_user_playlist
|
from spotify.tasks.play_user_playlist import play_user_playlist as play_user_playlist
|
||||||
|
from spotframework.model.track import SpotifyTrack
|
||||||
|
from spotframework.model.uri import Uri
|
||||||
|
from spotframework.model.service import Context
|
||||||
|
from spotframework.player.player import Player
|
||||||
|
|
||||||
import spotify.db.database as database
|
import spotify.db.database as database
|
||||||
|
|
||||||
@ -110,13 +114,90 @@ def cloud_task(func):
|
|||||||
return cloud_task_wrapper
|
return cloud_task_wrapper
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint.route('/play', methods=['POST'])
|
||||||
|
@login_or_basic_auth
|
||||||
|
def play(username=None):
|
||||||
|
user_ref = database.get_user_doc_ref(username)
|
||||||
|
user_dict = user_ref.get().to_dict()
|
||||||
|
|
||||||
|
if user_dict.get('spotify_linked', None):
|
||||||
|
request_json = request.get_json()
|
||||||
|
|
||||||
|
if 'uri' in request_json:
|
||||||
|
try:
|
||||||
|
uri = Uri(request_json['uri'])
|
||||||
|
if uri.object_type in [Uri.ObjectType.album, Uri.ObjectType.artist, Uri.ObjectType.playlist]:
|
||||||
|
context = Context(uri)
|
||||||
|
|
||||||
|
net = database.get_authed_network(username)
|
||||||
|
|
||||||
|
player = Player(net)
|
||||||
|
device = None
|
||||||
|
if 'device_name' in request_json:
|
||||||
|
devices = net.get_available_devices()
|
||||||
|
device = next((i for i in devices if i.name == request_json['device_name']), None)
|
||||||
|
|
||||||
|
player.play(context=context, device=device)
|
||||||
|
logger.info(f'played {uri}')
|
||||||
|
return jsonify({'message': 'played', 'status': 'success'}), 200
|
||||||
|
else:
|
||||||
|
return jsonify({'error': "uri not context compatible"}), 400
|
||||||
|
except ValueError:
|
||||||
|
return jsonify({'error': "malformed uri provided"}), 400
|
||||||
|
elif 'playlist_name' in request_json:
|
||||||
|
net = database.get_authed_network(username)
|
||||||
|
playlists = net.get_playlists()
|
||||||
|
if playlists is not None:
|
||||||
|
playlist_to_play = next((i for i in playlists if i.name == request_json['playlist_name']), None)
|
||||||
|
|
||||||
|
if playlist_to_play is not None:
|
||||||
|
player = Player(net)
|
||||||
|
device = None
|
||||||
|
if 'device_name' in request_json:
|
||||||
|
devices = net.get_available_devices()
|
||||||
|
device = next((i for i in devices if i.name == request_json['device_name']), None)
|
||||||
|
|
||||||
|
player.play(context=Context(playlist_to_play.uri), device=device)
|
||||||
|
logger.info(f'played {request_json["playlist_name"]}')
|
||||||
|
return jsonify({'message': 'played', 'status': 'success'}), 200
|
||||||
|
else:
|
||||||
|
return jsonify({'error': f"playlist {request_json['playlist_name']} not found"}), 404
|
||||||
|
else:
|
||||||
|
return jsonify({'error': "playlists not returned"}), 400
|
||||||
|
elif 'tracks' in request_json:
|
||||||
|
try:
|
||||||
|
uris = [Uri(i) for i in request_json['tracks']]
|
||||||
|
uris = [SpotifyTrack.get_uri_shell(i) for i in uris if i.object_type == Uri.ObjectType.track]
|
||||||
|
|
||||||
|
if len(uris) > 0:
|
||||||
|
net = database.get_authed_network(username)
|
||||||
|
|
||||||
|
player = Player(net)
|
||||||
|
device = None
|
||||||
|
if 'device_name' in request_json:
|
||||||
|
devices = net.get_available_devices()
|
||||||
|
device = next((i for i in devices if i.name == request_json['device_name']), None)
|
||||||
|
|
||||||
|
player.play(tracks=uris, device=device)
|
||||||
|
logger.info(f'played tracks')
|
||||||
|
return jsonify({'message': 'played', 'status': 'success'}), 200
|
||||||
|
else:
|
||||||
|
return jsonify({'error': "no track uris provided"}), 400
|
||||||
|
except ValueError:
|
||||||
|
return jsonify({'error': "uris failed to parse"}), 400
|
||||||
|
else:
|
||||||
|
return jsonify({'error': "no uris provided"}), 400
|
||||||
|
else:
|
||||||
|
return jsonify({'error': "spotify not linked"}), 400
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/playlists', methods=['GET'])
|
@blueprint.route('/playlists', methods=['GET'])
|
||||||
@login_or_basic_auth
|
@login_or_basic_auth
|
||||||
def get_playlists(username=None):
|
def get_playlists(username=None):
|
||||||
|
|
||||||
pulled_user = database.get_user_doc_ref(username)
|
user_ref = database.get_user_doc_ref(username)
|
||||||
|
|
||||||
playlists = pulled_user.collection(u'playlists')
|
playlists = user_ref.collection(u'playlists')
|
||||||
|
|
||||||
playlist_docs = [i.to_dict() for i in playlists.stream()]
|
playlist_docs = [i.to_dict() for i in playlists.stream()]
|
||||||
|
|
||||||
|
@ -2,8 +2,7 @@ from google.cloud import firestore
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from spotframework.net.user import NetworkUser
|
import spotify.db.database as database
|
||||||
from spotframework.net.network import Network
|
|
||||||
|
|
||||||
db = firestore.Client()
|
db = firestore.Client()
|
||||||
|
|
||||||
@ -18,13 +17,7 @@ def create_playlist(username, name):
|
|||||||
|
|
||||||
if len(users) == 1:
|
if len(users) == 1:
|
||||||
|
|
||||||
user_dict = users[0].to_dict()
|
net = database.get_authed_network(username)
|
||||||
spotify_keys = db.document('key/spotify').get().to_dict()
|
|
||||||
|
|
||||||
net = Network(NetworkUser(spotify_keys['clientid'],
|
|
||||||
spotify_keys['clientsecret'],
|
|
||||||
user_dict['refresh_token'],
|
|
||||||
user_dict['access_token']))
|
|
||||||
|
|
||||||
playlist = net.create_playlist(net.user.username, name)
|
playlist = net.create_playlist(net.user.username, name)
|
||||||
|
|
||||||
|
@ -1,13 +1,59 @@
|
|||||||
from google.cloud import firestore
|
from google.cloud import firestore
|
||||||
import logging
|
import logging
|
||||||
|
from datetime import timedelta, datetime, timezone
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from werkzeug.security import check_password_hash
|
from werkzeug.security import check_password_hash
|
||||||
|
|
||||||
|
from spotframework.net.network import Network
|
||||||
|
from spotify.db.user import DatabaseUser
|
||||||
|
|
||||||
db = firestore.Client()
|
db = firestore.Client()
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_token_database_callback(user):
|
||||||
|
if isinstance(user, DatabaseUser):
|
||||||
|
user_ref = get_user_doc_ref(user.user_id)
|
||||||
|
|
||||||
|
user_ref.update({
|
||||||
|
'access_token': user.accesstoken,
|
||||||
|
'last_refreshed': user.last_refreshed,
|
||||||
|
'token_expiry': user.token_expiry
|
||||||
|
})
|
||||||
|
logger.debug(f'{user.user_id} database entry updated')
|
||||||
|
else:
|
||||||
|
logger.error('user has no attached id')
|
||||||
|
|
||||||
|
|
||||||
|
def get_authed_network(username):
|
||||||
|
|
||||||
|
user = get_user_doc_ref(username)
|
||||||
|
if user:
|
||||||
|
user_dict = user.get().to_dict()
|
||||||
|
|
||||||
|
if user_dict.get('spotify_linked', None):
|
||||||
|
spotify_keys = db.document('key/spotify').get().to_dict()
|
||||||
|
|
||||||
|
user_obj = DatabaseUser(client_id=spotify_keys['clientid'],
|
||||||
|
client_secret=spotify_keys['clientsecret'],
|
||||||
|
refresh_token=user_dict['refresh_token'],
|
||||||
|
user_id=username,
|
||||||
|
access_token=user_dict['access_token'])
|
||||||
|
user_obj.on_refresh.append(refresh_token_database_callback)
|
||||||
|
|
||||||
|
if user_dict['last_refreshed'] + timedelta(seconds=user_dict['token_expiry'] - 1) \
|
||||||
|
< datetime.now(timezone.utc):
|
||||||
|
user_obj.refresh_token()
|
||||||
|
|
||||||
|
user_obj.refresh_info()
|
||||||
|
return Network(user_obj)
|
||||||
|
else:
|
||||||
|
logger.error('user spotify not linked')
|
||||||
|
else:
|
||||||
|
logger.error(f'user {username} not found')
|
||||||
|
|
||||||
|
|
||||||
def check_user_password(username, password):
|
def check_user_password(username, password):
|
||||||
|
|
||||||
user = get_user_doc_ref(user=username)
|
user = get_user_doc_ref(user=username)
|
||||||
@ -93,7 +139,7 @@ def get_user_playlist_ref_by_user_ref(user_ref: firestore.DocumentReference,
|
|||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(f'{username} multiple response playlists found for {playlist}')
|
logger.error(f'{username} multiple response playlists found for {playlist}')
|
||||||
return query
|
return query[0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(f'{username} no playlist found for {playlist}')
|
logger.error(f'{username} no playlist found for {playlist}')
|
||||||
|
9
spotify/db/user.py
Normal file
9
spotify/db/user.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from spotframework.net.user import NetworkUser
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseUser(NetworkUser):
|
||||||
|
|
||||||
|
def __init__(self, client_id, client_secret, refresh_token, user_id, access_token=None):
|
||||||
|
super().__init__(client_id=client_id, client_secret=client_secret,
|
||||||
|
refresh_token=refresh_token, access_token=access_token)
|
||||||
|
self.user_id = user_id
|
@ -8,8 +8,6 @@ from spotframework.engine.processor.shuffle import Shuffle
|
|||||||
from spotframework.engine.processor.sort import SortReleaseDate
|
from spotframework.engine.processor.sort import SortReleaseDate
|
||||||
from spotframework.engine.processor.deduplicate import DeduplicateByID
|
from spotframework.engine.processor.deduplicate import DeduplicateByID
|
||||||
|
|
||||||
from spotframework.net.network import Network
|
|
||||||
from spotframework.net.user import NetworkUser
|
|
||||||
from spotframework.player.player import Player
|
from spotframework.player.player import Player
|
||||||
import spotify.db.database as database
|
import spotify.db.database as database
|
||||||
from spotify.db.part_generator import PartGenerator
|
from spotify.db.part_generator import PartGenerator
|
||||||
@ -37,8 +35,6 @@ def play_user_playlist(username,
|
|||||||
|
|
||||||
if len(users) == 1:
|
if len(users) == 1:
|
||||||
|
|
||||||
user_dict = users[0].to_dict()
|
|
||||||
|
|
||||||
if parts is None and playlists is None:
|
if parts is None and playlists is None:
|
||||||
logger.critical(f'no playlists to use for creation ({username})')
|
logger.critical(f'no playlists to use for creation ({username})')
|
||||||
return None
|
return None
|
||||||
@ -53,12 +49,7 @@ def play_user_playlist(username,
|
|||||||
logger.critical(f'no playlists to use for creation ({username})')
|
logger.critical(f'no playlists to use for creation ({username})')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
spotify_keys = db.document('key/spotify').get().to_dict()
|
net = database.get_authed_network(username)
|
||||||
|
|
||||||
net = Network(NetworkUser(spotify_keys['clientid'],
|
|
||||||
spotify_keys['clientsecret'],
|
|
||||||
user_dict['refresh_token'],
|
|
||||||
user_dict['access_token']))
|
|
||||||
|
|
||||||
device = None
|
device = None
|
||||||
if device_name:
|
if device_name:
|
||||||
|
@ -10,8 +10,6 @@ from spotframework.engine.processor.deduplicate import DeduplicateByID
|
|||||||
|
|
||||||
from spotframework.model.uri import Uri
|
from spotframework.model.uri import Uri
|
||||||
|
|
||||||
from spotframework.net.network import Network
|
|
||||||
from spotframework.net.user import NetworkUser
|
|
||||||
import spotify.db.database as database
|
import spotify.db.database as database
|
||||||
from spotify.db.part_generator import PartGenerator
|
from spotify.db.part_generator import PartGenerator
|
||||||
|
|
||||||
@ -28,8 +26,6 @@ def run_user_playlist(username, playlist_name):
|
|||||||
|
|
||||||
if len(users) == 1:
|
if len(users) == 1:
|
||||||
|
|
||||||
user_dict = users[0].to_dict()
|
|
||||||
|
|
||||||
playlist_collection = db.collection(u'spotify_users', u'{}'.format(users[0].id), 'playlists')
|
playlist_collection = db.collection(u'spotify_users', u'{}'.format(users[0].id), 'playlists')
|
||||||
|
|
||||||
playlists = [i for i in playlist_collection.where(u'name', u'==', playlist_name).stream()]
|
playlists = [i for i in playlist_collection.where(u'name', u'==', playlist_name).stream()]
|
||||||
@ -46,12 +42,7 @@ def run_user_playlist(username, playlist_name):
|
|||||||
logger.critical(f'no playlists to use for creation ({username}/{playlist_name})')
|
logger.critical(f'no playlists to use for creation ({username}/{playlist_name})')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
spotify_keys = db.document('key/spotify').get().to_dict()
|
net = database.get_authed_network(username)
|
||||||
|
|
||||||
net = Network(NetworkUser(spotify_keys['clientid'],
|
|
||||||
spotify_keys['clientsecret'],
|
|
||||||
user_dict['refresh_token'],
|
|
||||||
user_dict['access_token']))
|
|
||||||
|
|
||||||
engine = PlaylistEngine(net)
|
engine = PlaylistEngine(net)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user