"""Application Handlers. Requests are redirected to handlers, which are responsible for getting information from the URL and passing it down to the logic layer. The way each layer talks to each other is through Response objects which defines the type status of the data and the data itself. Please note: the Orchard uses the term handlers over views as convention for clarity See: oto.response for more details. """ from flask import g from flask import jsonify, request from oto import response from oto.adaptors.flask import flaskify from owsrequest.flask_request import request_context_from_headers from lyrics import config from lyrics import exceptions from lyrics.api import app from lyrics.constants import header from lyrics.logic import lyrics as lyrics_logic from lyrics.schemas import lyrics_schema from lyrics.utils import handlers as handlers_utils @app.route(config.HEALTH_CHECK, methods=['GET']) def health(): """Check the health of the application.""" return jsonify({'status': 'ok'}) @app.errorhandler(500) def exception_handler(error): """Handle error when uncaught exception is raised. Default exception handler. Note: Exception will also be sent to Sentry if config.SENTRY is set. Returns: flask.Response: A 500 response with JSON 'code' & 'message' payload. """ message = ( 'The server encountered an internal error ' 'and was unable to complete your request.') g.log.exception(error) return flaskify(response.create_fatal_response(message)) @app.errorhandler(exceptions.RequestError) def handle_request_error(error): """Handle request and validation errors.""" return error.make_flask_response() @app.route('/tracks//lyrics', methods=['GET']) @handlers_utils.verify_authorization @handlers_utils.no_grass_access def get_track_lyrics(track_id): """Fetch track lyrics. Args: track_id (int): The track primary key. Returns: flask.Response: on successful, 200 status with JSON body. """ return flaskify(lyrics_logic.get_lyrics(track_id)) @app.route('/tracks//lyrics', methods=['PUT']) @handlers_utils.verify_authorization @handlers_utils.no_grass_access def put_track_lyrics(track_id): """Put track lyrics. Args: track_id (int): The track primary key. Returns: flask.Response: on successful, 200 status with JSON body. """ body = handlers_utils.parse_request_json( schema=lyrics_schema.LyricsPutSchema) return flaskify(lyrics_logic.put_lyrics(track_id, body['lyrics'])) @app.route('/tracks//lyrics', methods=['DELETE']) @handlers_utils.verify_authorization @handlers_utils.no_grass_access def delete_track_lyrics(track_id): """Delete track lyrics. Args: track_id (int): The track primary key. Returns: flask.Response: on successful, 200 status with JSON body. """ return flaskify(lyrics_logic.delete_lyrics(track_id)) @app.route('/tracks/lyrics', methods=['DELETE']) @handlers_utils.verify_authorization @handlers_utils.no_grass_access def delete_tracks_lyrics(): """Delete tracks lyrics. Returns: flask.Response: on successful, 200 status with JSON body. """ body = handlers_utils.parse_request_json( schema=lyrics_schema.LyricsDeleteSchema) return flaskify(lyrics_logic.delete_tracks_lyrics(body['tuids'])) @app.route('/tracks/copy', methods=['POST']) @handlers_utils.verify_authorization @handlers_utils.no_grass_access def copy_track_lyrics(): """Copy track lyrics. Returns: response.Response: empty response if success. """ body = handlers_utils.parse_request_json( schema=lyrics_schema.LyricsCopySchema) return flaskify(lyrics_logic.copy_lyrics(body['items'])) @app.route('/tracks/lyrics', methods=['GET', 'POST']) @handlers_utils.verify_authorization @request_context_from_headers() def get_bulk_track_lyrics(): """Fetch multiple track lyrics by track id. Returns: flask.Response: on successful, 200 status with JSON body. """ tuids = request.args.get('tuids') if request.method == 'POST': tuids = request.get_json('tuids')['tuids'] # Only OA Access.(Skip profile check for m2m calls, context_type is None) if g.request_context.context_type is not None: access_response = handlers_utils.verify_profile( g.request_context, header.PROFILE_TYPE_ORCH_ADMIN) if access_response.status != 200: return flaskify(access_response) return flaskify(lyrics_logic.bulk_track_lyrics(tuids)) @app.route('/has-explicit-lyrics', methods=['GET']) @handlers_utils.verify_authorization def has_explicit_lyrics(): """Determine if lyrics have explicit words. Returns: flask.Response: on successful, 200 status with JSON body of {has_explicit_lyrics: Boolean}. """ return flaskify(lyrics_logic.has_explicit_lyrics( request.args.get('lyrics'))) @app.route('/has-explicit-lyrics', methods=['POST']) @handlers_utils.verify_authorization def has_explicit_lyrics_post(): """Determine if lyrics have explicit words. Returns: flask.Response: on successful, 200 status with JSON body of {has_explicit_lyrics: Boolean}. """ body = handlers_utils.parse_request_json( schema=lyrics_schema.LyricsHasExplicitSchema) return flaskify(lyrics_logic.has_explicit_lyrics( body['lyrics']))