diff --git a/music/api/api.py b/music/api/api.py index dd02c3a..49aa914 100644 --- a/music/api/api.py +++ b/music/api/api.py @@ -8,10 +8,8 @@ import logging from datetime import datetime from music.api.decorators import login_required, login_or_basic_auth, admin_required, gae_cron, cloud_task -from music.cloud.tasks import execute_all_user_playlists, execute_user_playlists, create_run_user_playlist_task, \ - create_play_user_playlist_task +from music.cloud.tasks import update_all_user_playlists, update_playlists, run_user_playlist_task from music.tasks.run_user_playlist import run_user_playlist as run_user_playlist -from music.tasks.play_user_playlist import play_user_playlist as play_user_playlist from music.model.user import User from music.model.playlist import Playlist @@ -25,7 +23,7 @@ logger = logging.getLogger(__name__) @blueprint.route('/playlists', methods=['GET']) @login_or_basic_auth -def get_playlists(user=None): +def all_playlists_route(user=None): assert user is not None return jsonify({ 'playlists': [i.to_dict() for i in Playlist.collection.parent(user.key).fetch()] @@ -188,8 +186,9 @@ def playlist_route(user=None): updating_playlist.chart_limit = playlist_chart_limit if playlist_type is not None: - # TODO check acceptable value - updating_playlist.type = playlist_type + playlist_type = playlist_type.strip().lower() + if playlist_type in ['default', 'recents', 'fmchart']: + updating_playlist.type = playlist_type updating_playlist.update() logger.info(f'updated {user.username} / {playlist_name}') @@ -241,7 +240,7 @@ def user_route(user=None): @blueprint.route('/users', methods=['GET']) @login_or_basic_auth @admin_required -def users(user=None): +def all_users_route(user=None): return jsonify({ 'accounts': [i.to_dict() for i in User.collection.fetch()] }), 200 @@ -274,82 +273,6 @@ def change_password(user=None): return jsonify({'error': 'malformed request, no old_password/new_password'}), 400 -@blueprint.route('/playlist/play', methods=['POST']) -@login_or_basic_auth -def play_playlist(user=None): - - request_json = request.get_json() - - request_parts = request_json.get('parts', None) - request_playlist_type = request_json.get('playlist_type', 'default') - request_playlists = request_json.get('playlists', None) - request_shuffle = request_json.get('shuffle', False) - request_include_recommendations = request_json.get('include_recommendations', True) - request_recommendation_sample = request_json.get('recommendation_sample', 10) - request_day_boundary = request_json.get('day_boundary', 10) - request_add_this_month = request_json.get('add_this_month', False) - request_add_last_month = request_json.get('add_last_month', False) - - request_device_name = request_json.get('device_name', None) - - logger.info(f'playing {user.username}') - - if (request_parts and len(request_parts) > 0) or (request_playlists and len(request_playlists) > 0): - - if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - create_play_user_playlist_task(user.username, - parts=request_parts, - playlist_type=request_playlist_type, - playlists=request_playlists, - shuffle=request_shuffle, - include_recommendations=request_include_recommendations, - recommendation_sample=request_recommendation_sample, - day_boundary=request_day_boundary, - add_this_month=request_add_this_month, - add_last_month=request_add_last_month, - device_name=request_device_name) - else: - play_user_playlist(user.username, - parts=request_parts, - playlist_type=request_playlist_type, - playlists=request_playlists, - shuffle=request_shuffle, - include_recommendations=request_include_recommendations, - recommendation_sample=request_recommendation_sample, - day_boundary=request_day_boundary, - add_this_month=request_add_this_month, - add_last_month=request_add_last_month, - device_name=request_device_name) - - return jsonify({'message': 'execution requested', 'status': 'success'}), 200 - else: - logger.error(f'no playlists/parts {user.username}') - return jsonify({'error': 'insufficient playlist sources'}), 400 - - -@blueprint.route('/playlist/play/task', methods=['POST']) -@cloud_task -def play_playlist_task(): - payload = request.get_data(as_text=True) - if payload: - payload = json.loads(payload) - logger.info(f'playing {payload["username"]}') - - play_user_playlist(payload['username'], - parts=payload['parts'], - playlist_type=payload['playlist_type'], - playlists=payload['playlists'], - shuffle=payload['shuffle'], - include_recommendations=payload['include_recommendations'], - recommendation_sample=payload['recommendation_sample'], - day_boundary=payload['day_boundary'], - add_this_month=payload['add_this_month'], - add_last_month=payload['add_last_month'], - device_name=payload['device_name']) - - return jsonify({'message': 'executed playlist', 'status': 'success'}), 200 - - @blueprint.route('/playlist/run', methods=['GET']) @login_or_basic_auth def run_playlist(user=None): @@ -359,7 +282,7 @@ def run_playlist(user=None): if playlist_name: if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - create_run_user_playlist_task(user.username, playlist_name) + run_user_playlist_task(user.username, playlist_name) else: run_user_playlist(user.username, playlist_name) @@ -394,7 +317,7 @@ def run_user(user=None): else: user_name = user.username - execute_user_playlists(user_name) + update_playlists(user_name) return jsonify({'message': 'executed user', 'status': 'success'}), 200 @@ -405,7 +328,7 @@ def run_user_task(): payload = request.get_data(as_text=True) if payload: - execute_user_playlists(payload) + update_playlists(payload) return jsonify({'message': 'executed user', 'status': 'success'}), 200 @@ -414,7 +337,7 @@ def run_user_task(): @admin_required def run_users(user=None): - execute_all_user_playlists() + update_all_user_playlists() return jsonify({'message': 'executed all users', 'status': 'success'}), 200 @@ -422,7 +345,7 @@ def run_users(user=None): @gae_cron def run_users_cron(): - execute_all_user_playlists() + update_all_user_playlists() return jsonify({'status': 'success'}), 200 diff --git a/music/api/spotfm.py b/music/api/spotfm.py index 6f7b7e6..ca9d06c 100644 --- a/music/api/spotfm.py +++ b/music/api/spotfm.py @@ -5,7 +5,7 @@ import os from music.api.decorators import admin_required, login_or_basic_auth, lastfm_username_required, spotify_link_required, cloud_task, gae_cron import music.db.database as database -from music.cloud.tasks import execute_all_user_playlist_stats, execute_user_playlist_stats, create_refresh_playlist_task +from music.cloud.tasks import refresh_all_user_playlist_stats, refresh_user_playlist_stats, refresh_playlist_task from music.tasks.refresh_lastfm_stats import refresh_lastfm_track_stats, \ refresh_lastfm_album_stats, \ refresh_lastfm_artist_stats @@ -74,7 +74,7 @@ def playlist_refresh(user=None): if playlist_name: if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - create_refresh_playlist_task(user.username, playlist_name) + refresh_playlist_task(user.username, playlist_name) else: refresh_lastfm_track_stats(user.username, playlist_name) refresh_lastfm_album_stats(user.username, playlist_name) @@ -136,14 +136,14 @@ def run_playlist_artist_task(): @login_or_basic_auth @admin_required def run_users(user=None): - execute_all_user_playlist_stats() + refresh_all_user_playlist_stats() return jsonify({'message': 'executed all users', 'status': 'success'}), 200 @blueprint.route('/playlist/refresh/users/cron', methods=['GET']) @gae_cron def run_users_task(): - execute_all_user_playlist_stats() + refresh_all_user_playlist_stats() return jsonify({'status': 'success'}), 200 @@ -156,7 +156,7 @@ def run_user(user=None): else: user_name = user.username - execute_user_playlist_stats(user_name) + refresh_user_playlist_stats(user_name) return jsonify({'message': 'executed user', 'status': 'success'}), 200 @@ -167,5 +167,5 @@ def run_user_task(): payload = request.get_data(as_text=True) if payload: - execute_user_playlist_stats(payload) + refresh_user_playlist_stats(payload) return jsonify({'message': 'executed user', 'status': 'success'}), 200 diff --git a/music/api/tag.py b/music/api/tag.py index 2bb26fe..c7aa9cf 100644 --- a/music/api/tag.py +++ b/music/api/tag.py @@ -2,9 +2,11 @@ from flask import Blueprint, jsonify, request import logging import os +import json -from music.api.decorators import login_or_basic_auth +from music.api.decorators import login_or_basic_auth, gae_cron, cloud_task from music.cloud.function import update_tag as serverless_update_tag +from music.cloud.tasks import update_all_user_tags from music.tasks.update_tag import update_tag from music.model.tag import Tag @@ -60,10 +62,7 @@ def put_tag(tag_id, user): if request_json.get('name'): db_tag.name = request_json['name'].strip() - update_required = False - if request_json.get('tracks') is not None: - update_required = True db_tag.tracks = [ { 'name': track['name'].strip(), @@ -74,7 +73,6 @@ def put_tag(tag_id, user): ] if request_json.get('albums') is not None: - update_required = True db_tag.albums = [ { 'name': album['name'].strip(), @@ -85,7 +83,6 @@ def put_tag(tag_id, user): ] if request_json.get('artists') is not None: - update_required = True db_tag.artists = [ { 'name': artist['name'].strip() @@ -96,13 +93,6 @@ def put_tag(tag_id, user): db_tag.update() - if update_required: - # queue serverless refresh - if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - serverless_update_tag(username=user.username, tag_id=tag_id) - else: - update_tag(username=user.username, tag_id=tag_id) - return jsonify({"message": 'tag updated', "status": "success"}), 200 @@ -113,7 +103,7 @@ def post_tag(tag_id, user): existing_ids = [i.tag_id for i in Tag.collection.parent(user.key).fetch()] while tag_id in existing_ids: - tag_id += '1' + tag_id += '_' tag = Tag(parent=user.key) tag.tag_id = tag_id @@ -144,3 +134,26 @@ def tag_refresh(tag_id, user=None): update_tag(username=user.username, tag_id=tag_id) return jsonify({"message": 'tag updated', "status": "success"}), 200 + + +@blueprint.route('/tag/update/task', methods=['POST']) +@cloud_task +def run_tag_task(): + + payload = request.get_data(as_text=True) + if payload: + payload = json.loads(payload) + + logger.info(f'running {payload["username"]} / {payload["tag_id"]}') + + serverless_update_tag(username=payload['username'], tag_id=payload['tag_id']) + + return jsonify({'message': 'executed playlist', 'status': 'success'}), 200 + + +@blueprint.route('/tag/update/users/cron', methods=['GET']) +@gae_cron +def run_tags_cron(): + + update_all_user_tags() + return jsonify({'status': 'success'}), 200 diff --git a/music/cloud/tasks.py b/music/cloud/tasks.py index 9d880f0..2552c1d 100644 --- a/music/cloud/tasks.py +++ b/music/cloud/tasks.py @@ -6,12 +6,12 @@ import logging from google.cloud import tasks_v2 from google.protobuf import timestamp_pb2 -from music.db import database as database from music.tasks.run_user_playlist import run_user_playlist from music.tasks.refresh_lastfm_stats import refresh_lastfm_track_stats from music.model.user import User from music.model.playlist import Playlist +from music.model.tag import Tag tasker = tasks_v2.CloudTasksClient() task_path = tasker.queue_path('sarsooxyz', 'europe-west2', 'spotify-executions') @@ -19,7 +19,7 @@ task_path = tasker.queue_path('sarsooxyz', 'europe-west2', 'spotify-executions') logger = logging.getLogger(__name__) -def execute_all_user_playlists(): +def update_all_user_playlists(): """Create user playlist refresh task for all users""" seconds_delay = 0 @@ -48,7 +48,7 @@ def execute_all_user_playlists(): seconds_delay += 30 -def execute_user_playlists(username): +def update_playlists(username): """Refresh all playlists for given user, environment dependent""" user = User.collection.filter('username', '==', username.strip().lower()).get() @@ -66,14 +66,14 @@ def execute_user_playlists(username): if iterate_playlist.uri is not None: if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - create_run_user_playlist_task(username, iterate_playlist.name, seconds_delay) + run_user_playlist_task(username, iterate_playlist.name, seconds_delay) else: run_user_playlist(username, iterate_playlist.name) seconds_delay += 6 -def create_run_user_playlist_task(username, playlist_name, delay=0): +def run_user_playlist_task(username, playlist_name, delay=0): """Create tasks for a users given playlist""" task = { @@ -101,54 +101,7 @@ def create_run_user_playlist_task(username, playlist_name, delay=0): tasker.create_task(task_path, task) -def create_play_user_playlist_task(username, - parts=None, - playlist_type='default', - playlists=None, - shuffle=False, - include_recommendations=False, - recommendation_sample=10, - day_boundary=10, - add_this_month=False, - add_last_month=False, - delay=0, - device_name=None): - """Create tasks for a users given scratch playlist""" - - task = { - 'app_engine_http_request': { # Specify the type of request. - 'http_method': 'POST', - 'relative_uri': '/api/playlist/play/task', - 'body': json.dumps({ - 'username': username, - 'playlist_type': playlist_type, - 'parts': parts, - 'playlists': playlists, - 'shuffle': shuffle, - 'include_recommendations': include_recommendations, - 'recommendation_sample': recommendation_sample, - 'day_boundary': day_boundary, - 'add_this_month': add_this_month, - 'add_last_month': add_last_month, - 'device_name': device_name - }).encode() - } - } - - if delay > 0: - d = datetime.datetime.utcnow() + datetime.timedelta(seconds=delay) - - # Create Timestamp protobuf. - timestamp = timestamp_pb2.Timestamp() - timestamp.FromDatetime(d) - - # Add the timestamp to the tasks. - task['schedule_time'] = timestamp - - tasker.create_task(task_path, task) - - -def execute_all_user_playlist_stats(): +def refresh_all_user_playlist_stats(): """"Create user playlist stats refresh task for all users""" seconds_delay = 0 @@ -160,9 +113,9 @@ def execute_all_user_playlist_stats(): len(iter_user.lastfm_username) > 0 and not iter_user.locked: if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - create_refresh_user_task(username=iter_user.username, delay=seconds_delay) + refresh_user_stats_task(username=iter_user.username, delay=seconds_delay) else: - execute_user_playlist_stats(username=iter_user.username) + refresh_user_playlist_stats(username=iter_user.username) seconds_delay += 2400 @@ -170,7 +123,7 @@ def execute_all_user_playlist_stats(): logger.debug(f'skipping {iter_user.username}') -def execute_user_playlist_stats(username): +def refresh_user_playlist_stats(username): """Refresh all playlist stats for given user, environment dependent""" user = User.collection.filter('username', '==', username.strip().lower()).get() @@ -188,7 +141,7 @@ def execute_user_playlist_stats(username): if playlist.uri is not None: if os.environ.get('DEPLOY_DESTINATION', None) == 'PROD': - create_refresh_playlist_task(username, playlist.name, seconds_delay) + refresh_playlist_task(username, playlist.name, seconds_delay) else: refresh_lastfm_track_stats(username, playlist.name) @@ -197,7 +150,7 @@ def execute_user_playlist_stats(username): logger.error('no last.fm username') -def create_refresh_user_task(username, delay=0): +def refresh_user_stats_task(username, delay=0): """Create user playlist stats refresh task""" task = { @@ -219,7 +172,7 @@ def create_refresh_user_task(username, delay=0): tasker.create_task(task_path, task) -def create_refresh_playlist_task(username, playlist_name, delay=0): +def refresh_playlist_task(username, playlist_name, delay=0): """Create user playlist stats refresh tasks""" track_task = { @@ -274,3 +227,37 @@ def create_refresh_playlist_task(username, playlist_name, delay=0): tasker.create_task(task_path, track_task) tasker.create_task(task_path, album_task) tasker.create_task(task_path, artist_task) + + +def update_all_user_tags(): + """Create user tag refresh task sfor all users""" + + seconds_delay = 0 + logger.info('running') + + for iter_user in User.collection.fetch(): + + if iter_user.lastfm_username and len(iter_user.lastfm_username) > 0 and not iter_user.locked: + + for tag in Tag.collection.parent(iter_user.key).fetch(): + + task = { + 'app_engine_http_request': { # Specify the type of request. + 'http_method': 'POST', + 'relative_uri': '/api/tag/update/task', + 'body': json.dumps({ + 'username': iter_user.username, + 'tag_id': tag.tag_id + }).encode() + } + } + + d = datetime.datetime.utcnow() + datetime.timedelta(seconds=seconds_delay) + + timestamp = timestamp_pb2.Timestamp() + timestamp.FromDatetime(d) + + task['schedule_time'] = timestamp + + tasker.create_task(task_path, task) + seconds_delay += 10 diff --git a/music/tasks/play_user_playlist.py b/music/tasks/play_user_playlist.py deleted file mode 100644 index 5ca68c5..0000000 --- a/music/tasks/play_user_playlist.py +++ /dev/null @@ -1,99 +0,0 @@ -import datetime -import logging - -from spotframework.engine.playlistengine import PlaylistEngine, PlaylistSource, RecommendationSource -from spotframework.engine.processor.shuffle import Shuffle -from spotframework.engine.processor.sort import SortReleaseDate -from spotframework.engine.processor.deduplicate import DeduplicateByID - -from spotframework.player.player import Player -import music.db.database as database -from music.db.part_generator import PartGenerator -from music.model.user import User - -logger = logging.getLogger(__name__) - - -def play_user_playlist(username, - playlist_type='default', - parts=None, - playlists=None, - shuffle=False, - include_recommendations=True, - recommendation_sample=10, - day_boundary=10, - add_this_month=False, - add_last_month=False, - device_name=None): - - user = User.collection.filter('username', '==', username.strip().lower()).get() - - if user is None: - logger.error(f'user {username} not found') - return - - logger.info(f'playing for {username}') - - if parts is None and playlists is None: - logger.critical(f'no playlists to use for creation ({username})') - return None - - if parts is None: - parts = [] - - if playlists is None: - playlists = [] - - if len(parts) == 0 and len(playlists) == 0: - logger.critical(f'no playlists to use for creation ({username})') - return None - - net = database.get_authed_spotify_network(user) - - device = None - if device_name: - devices = net.get_available_devices() - if devices and len(devices) > 0: - device = next((i for i in devices if i.name == device_name), None) - if device is None: - logger.error(f'error selecting device {device_name} to play on') - else: - logger.warning(f'no available devices to play') - - engine = PlaylistEngine(net) - - player = Player(net) - - processors = [DeduplicateByID()] - - if shuffle: - processors.append(Shuffle()) - else: - processors.append(SortReleaseDate(reverse=True)) - - submit_parts = parts - - part_generator = PartGenerator(user=user) - - for part in playlists: - submit_parts += part_generator.get_recursive_parts(part) - - submit_parts = [i for i in {j for j in submit_parts}] - - params = [ - PlaylistSource.Params(names=submit_parts, processors=processors) - ] - - if include_recommendations: - params.append(RecommendationSource.Params(recommendation_limit=int(recommendation_sample))) - - if playlist_type == 'recents': - boundary_date = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=int(day_boundary)) - tracks = engine.get_recent_playlist(params=params, - boundary_date=boundary_date, - add_this_month=add_this_month, - add_last_month=add_last_month) - else: - tracks = engine.make_playlist(params=params) - - player.play(tracks=tracks, device=device) diff --git a/requirements.txt b/requirements.txt index b8889c9..033e195 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,20 +1,20 @@ -astroid==2.4.0 +astroid==2.4.1 cachetools==4.1.0 certifi==2020.4.5.1 chardet==3.0.4 click==7.1.2 -fireo==1.2.4 +fireo==1.2.8 Flask==1.1.2 google-api-core==1.17.0 -google-auth==1.14.1 +google-auth==1.14.3 google-cloud-core==1.3.0 google-cloud-firestore==1.6.2 google-cloud-logging==1.15.0 -google-cloud-pubsub==1.4.3 +google-cloud-pubsub==1.5.0 google-cloud-tasks==1.5.0 googleapis-common-protos==1.51.0 grpc-google-iam-v1==0.12.3 -grpcio==1.28.1 +grpcio==1.29.0 idna==2.9 isort==4.3.21 itsdangerous==1.1.0 @@ -22,18 +22,18 @@ Jinja2==2.11.2 lazy-object-proxy==1.4.3 MarkupSafe==1.1.1 mccabe==0.6.1 -numpy==1.18.3 +numpy==1.18.4 opencv-python==4.2.0.34 protobuf==3.11.3 pyasn1==0.4.8 pyasn1-modules==0.2.8 -pylint==2.5.0 +pylint==2.5.2 pytz==2020.1 requests==2.23.0 rsa==4.0 six==1.14.0 tabulate==0.8.7 -toml==0.10.0 +toml==0.10.1 urllib3==1.25.9 Werkzeug==1.0.1 wrapt==1.12.1 diff --git a/src/js/Playlist/AllPlaylistsRouter.js b/src/js/Playlist/AllPlaylistsRouter.js index 6f95c59..f6438f7 100644 --- a/src/js/Playlist/AllPlaylistsRouter.js +++ b/src/js/Playlist/AllPlaylistsRouter.js @@ -3,7 +3,6 @@ import { Route, Switch } from "react-router-dom"; import PlaylistsView from "./PlaylistsList.js" import NewPlaylist from "./New.js"; -import ScratchView from "./ScratchView.js"; class Playlists extends Component { render(){ @@ -12,7 +11,6 @@ class Playlists extends Component { - ); diff --git a/src/js/Playlist/ScratchView.js b/src/js/Playlist/ScratchView.js deleted file mode 100644 index e60c757..0000000 --- a/src/js/Playlist/ScratchView.js +++ /dev/null @@ -1,410 +0,0 @@ -import React, { Component } from "react"; -const axios = require('axios'); - -import showMessage from "../Toast.js" - -var thisMonth = [ - 'january', - 'february', - 'march', - 'april', - 'may', - 'june', - 'july', - 'august', - 'septempber', - 'october', - 'november', - 'december' -]; - -var lastMonth = [ - 'december', - 'january', - 'february', - 'march', - 'april', - 'may', - 'june', - 'july', - 'august', - 'septempber', - 'october', - 'november' -]; - -class ScratchView extends Component{ - - constructor(props){ - super(props); - this.state = { - name: 'play', - parts: [], - playlists: [], - filteredPlaylists: [], - playlist_references: [], - type: 'default', - - day_boundary: 5, - recommendation_sample: 5, - newPlaylistName: '', - newReferenceName: '', - - shuffle: false, - include_recommendations: false, - add_this_month: false, - add_last_month: false - } - this.handleAddPart = this.handleAddPart.bind(this); - this.handleAddReference = this.handleAddReference.bind(this); - this.handleInputChange = this.handleInputChange.bind(this); - this.handleRemovePart = this.handleRemovePart.bind(this); - this.handleRemoveReference = this.handleRemoveReference.bind(this); - - this.handleRun = this.handleRun.bind(this); - - this.handleShuffleChange = this.handleShuffleChange.bind(this); - this.handleIncludeRecommendationsChange = this.handleIncludeRecommendationsChange.bind(this); - this.handleThisMonthChange = this.handleThisMonthChange.bind(this); - this.handleLastMonthChange = this.handleLastMonthChange.bind(this); - } - - componentDidMount(){ - - this.getPlaylists(); - } - - - getPlaylists(){ - return axios.get(`/api/playlists`) - .then((response) => { - var filteredPlaylists = response.data.playlists.filter((entry) => entry.name != this.state.name); - - this.setState({ - playlists: response.data.playlists, - newReferenceName: filteredPlaylists.length > 0 ? filteredPlaylists[0].name : '' - }); - }) - .catch((error) => { - showMessage(`Error Getting Playlists (${error.response.status})`); - }); - } - - handleInputChange(event){ - this.setState({ - [event.target.name]: event.target.value - }); - } - - handleShuffleChange(event) { - this.setState({ - shuffle: event.target.checked - }); - } - - handleThisMonthChange(event) { - this.setState({ - add_this_month: event.target.checked - }); - } - - handleLastMonthChange(event) { - this.setState({ - add_last_month: event.target.checked - }); - } - - handleIncludeRecommendationsChange(event) { - this.setState({ - include_recommendations: event.target.checked - }); - } - - handleAddPart(event){ - - if(this.state.newPlaylistName.length != 0){ - - var check = this.state.parts.includes(this.state.newPlaylistName); - - if(check == false) { - var parts = this.state.parts.slice(); - parts.push(this.state.newPlaylistName); - - parts.sort(function(a, b){ - if(a < b) { return -1; } - if(a > b) { return 1; } - return 0; - }); - - this.setState({ - parts: parts, - newPlaylistName: '' - }); - }else{ - showMessage('Playlist Already Added'); - } - - }else{ - showMessage('Enter Playlist Name'); - } - } - - handleAddReference(event){ - - if(this.state.newReferenceName.length != 0){ - - var check = this.state.playlist_references.includes(this.state.newReferenceName); - - if(check == false) { - var playlist_references = this.state.playlist_references.slice(); - playlist_references.push(this.state.newReferenceName); - - playlist_references.sort(function(a, b){ - if(a < b) { return -1; } - if(a > b) { return 1; } - return 0; - }); - - var filteredPlaylists = this.state.playlists.filter((entry) => entry.name != this.state.name); - - this.setState({ - playlist_references: playlist_references, - newReferenceName: filteredPlaylists.length > 0 ? filteredPlaylists[0].name : '' - }); - - }else{ - showMessage('Playlist Already Added'); - } - - }else{ - showMessage('No Other Playlists To Add'); - } - } - - handleRemovePart(id, event){ - var parts = this.state.parts; - parts = parts.filter(e => e !== id); - this.setState({ - parts: parts - }); - - if(parts.length == 0) { - parts = -1; - } - } - - handleRemoveReference(id, event){ - var playlist_references = this.state.playlist_references; - playlist_references = playlist_references.filter(e => e !== id); - this.setState({ - playlist_references: playlist_references - }); - } - - handleRun(event){ - if(this.state.playlist_references.length > 0 || this.state.parts.length > 0){ - axios.get('/api/user') - .then((response) => { - if(response.data.spotify_linked == true){ - axios.post('/api/playlist/play', { - parts: this.state.parts, - playlists: this.state.playlist_references, - shuffle: this.state.shuffle, - include_recommendations: this.state.include_recommendations, - recommendation_sample: this.state.recommendation_sample, - day_boundary: this.state.day_boundary, - playlist_type: this.state.type, - add_this_month: this.state.add_this_month, - add_last_month: this.state.add_last_month - }) - .then((reponse) => { - showMessage(`Played`); - }) - .catch((error) => { - showMessage(`Error Playing (${error.response.status})`); - }); - }else{ - showMessage(`Link Spotify Before Running`); - } - }).catch((error) => { - showMessage(`Error Playing (${error.response.status})`); - }); - }else{ - showMessage(`Add Either Playlists Or Parts`); - } - } - - render(){ - - var date = new Date(); - - const table = ( - - {/* - - - - */} - { this.state.playlist_references.length > 0 && } - { this.state.parts.length > 0 && } - - - - - - - - - - - - - - - - - - - - - - - - - { this.state.type == 'recents' && - - - - - } - { this.state.type == 'recents' && - - - - - } - { this.state.type == 'recents' && - - - - - } - - - - - - - - -

{ this.state.name }

-

Spotify playlist can be the name of either your own created playlist or one you follow, names are case sensitive -
- - - -
- - - -
- Shuffle Output - - -
- Include Recommendations - - -
- Recommendation Size - - -
- Added Since (Days) - - -
- Include {thisMonth[date.getMonth()]} Playlist - - -
- Include {lastMonth[date.getMonth()]} Playlist - - -
- Type - - -
- -
- ); - - const error =

{ this.state.error_text }

; - - return this.state.error ? error : table; - } - -} - -function ReferenceEntry(props) { - return ( - - ); -} - -function ListBlock(props) { - return ( - - {props.name} - { props.list.map((part) => ) } - - ); -} - -function Row (props) { - return ( - - { props.part } - - - ); -} - -export default ScratchView; \ No newline at end of file