2019-09-30 14:19:00 +01:00
|
|
|
from flask import Blueprint, request, jsonify
|
|
|
|
|
|
|
|
import logging
|
|
|
|
|
2020-07-29 10:45:40 +01:00
|
|
|
from music.api.decorators import login_or_basic_auth, spotify_link_required, validate_json
|
2019-10-19 17:14:11 +01:00
|
|
|
import music.db.database as database
|
2019-09-30 14:19:00 +01:00
|
|
|
|
2020-06-22 20:21:54 +01:00
|
|
|
from spotframework.net.network import SpotifyNetworkException
|
|
|
|
from spotframework.model.track import Context
|
2019-09-30 14:19:00 +01:00
|
|
|
from spotframework.model.uri import Uri
|
|
|
|
from spotframework.player.player import Player
|
|
|
|
|
|
|
|
blueprint = Blueprint('player_api', __name__)
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route('/play', methods=['POST'])
|
|
|
|
@login_or_basic_auth
|
|
|
|
@spotify_link_required
|
2020-04-30 14:54:05 +01:00
|
|
|
def play(user=None):
|
2019-09-30 14:19:00 +01:00
|
|
|
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)
|
|
|
|
|
2020-04-30 14:54:05 +01:00
|
|
|
net = database.get_authed_spotify_network(user)
|
2019-09-30 14:19:00 +01:00
|
|
|
|
|
|
|
player = Player(net)
|
2019-10-01 19:20:22 +01:00
|
|
|
player.play(context=context, device_name=request_json.get('device_name', None))
|
2019-09-30 14:19:00 +01:00
|
|
|
|
|
|
|
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:
|
2020-04-30 14:54:05 +01:00
|
|
|
net = database.get_authed_spotify_network(user)
|
2020-06-22 20:21:54 +01:00
|
|
|
try:
|
|
|
|
playlists = net.get_playlists()
|
2019-09-30 14:19:00 +01:00
|
|
|
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)
|
2019-10-01 19:20:22 +01:00
|
|
|
player.play(context=Context(playlist_to_play.uri), device_name=request_json.get('device_name', None))
|
2019-09-30 14:19:00 +01:00
|
|
|
|
|
|
|
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
|
2020-06-22 20:21:54 +01:00
|
|
|
except SpotifyNetworkException:
|
2020-07-01 11:03:43 +01:00
|
|
|
logger.exception(f'error occured during {user.username} playlists retrieval')
|
2019-09-30 14:19:00 +01:00
|
|
|
return jsonify({'error': "playlists not returned"}), 400
|
2020-06-22 20:21:54 +01:00
|
|
|
|
2019-09-30 14:19:00 +01:00
|
|
|
elif 'tracks' in request_json:
|
|
|
|
try:
|
|
|
|
uris = [Uri(i) for i in request_json['tracks']]
|
|
|
|
|
2020-06-21 15:30:51 +01:00
|
|
|
# TODO check uri object type
|
2019-09-30 14:19:00 +01:00
|
|
|
if len(uris) > 0:
|
2020-04-30 14:54:05 +01:00
|
|
|
net = database.get_authed_spotify_network(user)
|
2019-09-30 14:19:00 +01:00
|
|
|
|
|
|
|
player = Player(net)
|
2020-06-21 15:30:51 +01:00
|
|
|
player.play(uris=uris, device_name=request_json.get('device_name', None))
|
2019-09-30 14:19:00 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route('/next', methods=['POST'])
|
|
|
|
@login_or_basic_auth
|
|
|
|
@spotify_link_required
|
2020-04-30 14:54:05 +01:00
|
|
|
def next_track(user=None):
|
|
|
|
net = database.get_authed_spotify_network(user)
|
2019-09-30 14:19:00 +01:00
|
|
|
player = Player(net)
|
|
|
|
|
|
|
|
player.next()
|
|
|
|
return jsonify({'message': 'skipped', 'status': 'success'}), 200
|
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route('/shuffle', methods=['POST'])
|
|
|
|
@login_or_basic_auth
|
|
|
|
@spotify_link_required
|
2020-07-29 10:45:40 +01:00
|
|
|
@validate_json(('state', bool))
|
2020-04-30 14:54:05 +01:00
|
|
|
def shuffle(user=None):
|
2019-09-30 14:19:00 +01:00
|
|
|
request_json = request.get_json()
|
|
|
|
|
2020-07-29 10:45:40 +01:00
|
|
|
net = database.get_authed_spotify_network(user)
|
|
|
|
player = Player(net)
|
2019-09-30 14:19:00 +01:00
|
|
|
|
2020-07-29 10:45:40 +01:00
|
|
|
player.shuffle(state=request_json['state'])
|
|
|
|
return jsonify({'message': f'shuffle set to {request_json["state"]}', 'status': 'success'}), 200
|
2019-09-30 14:19:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
@blueprint.route('/volume', methods=['POST'])
|
|
|
|
@login_or_basic_auth
|
|
|
|
@spotify_link_required
|
2020-07-29 10:45:40 +01:00
|
|
|
@validate_json(('volume', int))
|
2020-04-30 14:54:05 +01:00
|
|
|
def volume(user=None):
|
2019-09-30 14:19:00 +01:00
|
|
|
request_json = request.get_json()
|
|
|
|
|
2020-07-29 10:45:40 +01:00
|
|
|
if 0 <= request_json['volume'] <= 100:
|
|
|
|
net = database.get_authed_spotify_network(user)
|
|
|
|
player = Player(net)
|
2019-09-30 14:19:00 +01:00
|
|
|
|
2020-07-29 10:45:40 +01:00
|
|
|
player.volume(value=request_json['volume'])
|
|
|
|
return jsonify({'message': f'volume set to {request_json["volume"]}', 'status': 'success'}), 200
|
2019-09-30 14:19:00 +01:00
|
|
|
else:
|
2020-07-29 10:45:40 +01:00
|
|
|
return jsonify({'error': "volume must be between 0 and 100"}), 400
|