imported spotframework, utilising for running playlists locally

This commit is contained in:
aj 2019-08-10 17:53:50 +01:00
parent 7272379a9c
commit 57408efcda
6 changed files with 146 additions and 30 deletions

View File

@ -7,6 +7,7 @@ google-api-core==1.14.2
google-auth==1.6.3 google-auth==1.6.3
google-cloud-core==1.0.3 google-cloud-core==1.0.3
google-cloud-firestore==1.4.0 google-cloud-firestore==1.4.0
google-cloud-logging==1.12.1
google-cloud-pubsub==0.45.0 google-cloud-pubsub==0.45.0
google-cloud-tasks==1.2.0 google-cloud-tasks==1.2.0
googleapis-common-protos==1.6.0 googleapis-common-protos==1.6.0

View File

@ -9,6 +9,8 @@ from google.cloud import tasks_v2
from google.protobuf import timestamp_pb2 from google.protobuf import timestamp_pb2
from werkzeug.security import check_password_hash, generate_password_hash from werkzeug.security import check_password_hash, generate_password_hash
from spotify.tasks.run_user_playlist import run_user_playlist as run_user_playlist
import spotify.api.database as database import spotify.api.database as database
blueprint = Blueprint('api', __name__) blueprint = Blueprint('api', __name__)
@ -307,7 +309,7 @@ def run_playlist():
if playlist_name: if playlist_name:
execute_playlist(session['username'], playlist_name) run_user_playlist(session['username'], playlist_name)
return jsonify({'message': 'execution requested', 'status': 'success'}), 200 return jsonify({'message': 'execution requested', 'status': 'success'}), 200
@ -325,7 +327,9 @@ def run_playlist_task():
payload = request.get_data(as_text=True) payload = request.get_data(as_text=True)
if payload: if payload:
payload = json.loads(payload) payload = json.loads(payload)
execute_playlist(payload['username'], payload['name'])
run_user_playlist(payload['username'], payload['name'])
return jsonify({'message': 'executed playlist', 'status': 'success'}), 200 return jsonify({'message': 'executed playlist', 'status': 'success'}), 200
else: else:
return jsonify({'error': 'unauthorized'}), 401 return jsonify({'error': 'unauthorized'}), 401
@ -455,7 +459,7 @@ def execute_user(username):
# execute_playlist(username, iterate_playlist['name']) # execute_playlist(username, iterate_playlist['name'])
def execute_playlist(username, name): def push_run_user_playlist_message(username, name):
data = u'{}'.format(name) data = u'{}'.format(name)
data = data.encode('utf-8') data = data.encode('utf-8')

View File

@ -1,7 +1,8 @@
import requests
from base64 import b64encode
from google.cloud import firestore from google.cloud import firestore
from spotframework.net.user import User
from spotframework.net.network import Network
db = firestore.Client() db = firestore.Client()
@ -14,30 +15,12 @@ def create_playlist(username, name):
user_dict = users[0].to_dict() user_dict = users[0].to_dict()
spotify_keys = db.document('key/spotify').get().to_dict() spotify_keys = db.document('key/spotify').get().to_dict()
idsecret = b64encode(bytes(spotify_keys['clientid'] + ':' + spotify_keys['clientsecret'], "utf-8")).decode("ascii") net = Network(User(spotify_keys['clientid'],
spotify_keys['clientsecret'],
user_dict['access_token'],
user_dict['refresh_token']))
token_headers = {'Authorization': 'Basic %s' % idsecret} net.create_playlist(net.user.username, name)
headers = {"Content-Type": "application/json"}
data = {"grant_type": "refresh_token", "refresh_token": user_dict['refresh_token']}
token_req = requests.post('https://accounts.spotify.com/api/token', data=data, headers=token_headers)
if 200 <= token_req.status_code < 300:
accesstoken = token_req.json()['access_token']
json = {"name": name, "public": True, "collaborative": False}
headers['Authorization'] = 'Bearer ' + accesstoken
info_id = requests.get('https://api.spotify.com/v1/me', headers=headers).json()['id']
play_req = requests.post(f'https://api.spotify.com/v1/users/{info_id}/playlists', json=json, headers=headers)
resp = play_req.json()
return resp["id"]
else: else:
print(token_req.status_code) raise ValueError('no/multiple username(s)')
raise Exception('failed to get access token')

View File

@ -2,13 +2,30 @@ from flask import Flask, render_template, redirect, request, session, flash, url
from google.cloud import firestore from google.cloud import firestore
import os import os
import logging
from spotify.auth import auth_blueprint from spotify.auth import auth_blueprint
from spotify.api import api_blueprint from spotify.api import api_blueprint
from google.cloud.logging.handlers import CloudLoggingHandler
from google.cloud import logging as glogging
# Project ID is determined by the GCLOUD_PROJECT environment variable # Project ID is determined by the GCLOUD_PROJECT environment variable
db = firestore.Client() db = firestore.Client()
logger = logging.getLogger(__name__)
logger.setLevel('INFO')
log_format = '%(levelname)s %(name)s:%(funcName)s - %(message)s'
formatter = logging.Formatter(log_format)
client = glogging.Client()
handler = CloudLoggingHandler(client)
handler.setFormatter(formatter)
logger.addHandler(handler)
app = Flask(__name__, static_folder=os.path.join(os.path.dirname(__file__), '..', 'build'), template_folder="templates") app = Flask(__name__, static_folder=os.path.join(os.path.dirname(__file__), '..', 'build'), template_folder="templates")
app.secret_key = db.collection(u'spotify').document(u'config').get().to_dict()['secret_key'] app.secret_key = db.collection(u'spotify').document(u'config').get().to_dict()['secret_key']
app.register_blueprint(auth_blueprint, url_prefix='/auth') app.register_blueprint(auth_blueprint, url_prefix='/auth')

View File

View File

@ -0,0 +1,111 @@
from google.cloud import firestore
import datetime
import logging
from spotframework.engine.playlistengine import PlaylistEngine
from spotframework.engine.filter.shuffle import Shuffle
from spotframework.engine.filter.sortreversereleasedate import SortReverseReleaseDate
from spotframework.engine.filter.deduplicatebyid import DeduplicateByID
from spotframework.net.network import Network
from spotframework.net.user import User
db = firestore.Client()
captured_playlists = []
def run_user_playlist(username, playlist_name):
logger = logging.getLogger(__name__)
users = [i for i in db.collection(u'spotify_users').where(u'username', u'==', username).stream()]
logger.info(f'{username} / {playlist_name}')
if len(users) == 1:
user_dict = users[0].to_dict()
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()]
if len(playlists) == 1:
playlist_dict = playlists[0].to_dict()
if playlist_dict['playlist_id'] is None:
logger.critical(f'no playlist id to populate ({username}/{playlist_name})')
return
if len(playlist_dict['parts']) == 0 and len(playlist_dict['playlist_references']) == 0:
logger.critical(f'no playlists to use for creation ({username}/{playlist_name})')
return
spotify_keys = db.document('key/spotify').get().to_dict()
net = Network(User(spotify_keys['clientid'],
spotify_keys['clientsecret'],
user_dict['access_token'],
user_dict['refresh_token']))
engine = PlaylistEngine(net)
engine.load_user_playlists()
processors = [DeduplicateByID()]
if playlist_dict['shuffle'] is True:
processors.append(Shuffle())
else:
processors.append(SortReverseReleaseDate())
global captured_playlists
captured_playlists = []
submit_parts = playlist_dict['parts'] + generate_parts(users[0].id, playlist_dict['name'])
submit_parts = [i for i in {j for j in submit_parts}]
if playlist_dict['type'] == 'recents':
boundary_date = datetime.datetime.now() - datetime.timedelta(days=int(playlist_dict['day_boundary']))
tracks = engine.get_recent_playlist(boundary_date,
submit_parts,
processors,
include_recommendations=playlist_dict['include_recommendations'],
recommendation_limit=int(playlist_dict['recommendation_sample']))
else:
tracks = engine.make_playlist(submit_parts,
processors,
include_recommendations=playlist_dict['include_recommendations'],
recommendation_limit=int(playlist_dict['recommendation_sample']))
engine.execute_playlist(tracks, playlist_dict['playlist_id'])
engine.change_description(sorted(submit_parts), playlist_dict['playlist_id'])
else:
logger.critical(f'multiple/no playlists found ({username}/{playlist_name})')
return
else:
logger.critical(f'multiple/no user(s) found ({username}/{playlist_name})')
return
def generate_parts(user_id, name):
playlist_doc = [i.to_dict() for i in
db.document(u'spotify_users/{}'.format(user_id))
.collection(u'playlists')
.where(u'name', '==', name).stream()][0]
return_parts = playlist_doc['parts']
captured_playlists.append(name)
for i in playlist_doc['playlist_references']:
if i not in captured_playlists:
return_parts += generate_parts(user_id, i)
return return_parts