def add_playlist_item(playlist_mbid, offset): """ Append recordings to an existing playlist by posting a playlist with one of more recordings in it. The playlist must be in JSPF format with MusicBrainz extensions, which is defined here: https://musicbrainz.org/doc/jspf . If the offset is provided in the URL, then the recordings will be added at that offset, otherwise they will be added at the end of the playlist. You may only add :data:`~webserver.views.playlist_api.MAX_RECORDINGS_PER_ADD` recordings in one call to this endpoint. :reqheader Authorization: Token <user token> :statuscode 200: playlist accepted. :statuscode 400: invalid JSON sent, see error message for details. :statuscode 401: invalid authorization. See error message for details. :statuscode 403: forbidden. the requesting user was not allowed to carry out this operation. :resheader Content-Type: *application/json* """ user = validate_auth_header() if offset is not None and offset < 0: log_raise_400("Offset must be a positive integer.") if not is_valid_uuid(playlist_mbid): log_raise_400("Provided playlist ID is invalid.") playlist = db_playlist.get_by_mbid(playlist_mbid) if playlist is None or not playlist.is_visible_by(user["id"]): raise APINotFound("Cannot find playlist: %s" % playlist_mbid) if not playlist.is_modifiable_by(user["id"]): raise APIForbidden( "You are not allowed to add recordings to this playlist.") data = request.json validate_playlist(data) if len(data["playlist"]["track"]) > MAX_RECORDINGS_PER_ADD: log_raise_400("You may only add max %d recordings per call." % MAX_RECORDINGS_PER_ADD) precordings = [] if "track" in data["playlist"]: for track in data["playlist"]["track"]: try: mbid = UUID( track['identifier'][len(PLAYLIST_TRACK_URI_PREFIX):]) except (KeyError, ValueError): log_raise_400( "Track %d has an invalid identifier field, it must be a complete URI." ) precordings.append( WritablePlaylistRecording(mbid=mbid, added_by_id=user["id"])) try: db_playlist.add_recordings_to_playlist(playlist, precordings, offset) except Exception as e: current_app.logger.error( "Error while adding recordings to playlist: {}".format(e)) raise APIInternalServerError( "Failed to add recordings to the playlist. Please try again.") return jsonify({'status': 'ok'})
def create_playlist(): """ Create a playlist. The playlist must be in JSPF format with MusicBrainz extensions, which is defined here: https://musicbrainz.org/doc/jspf . To create an empty playlist, you can send an empty playlist with only the title field filled out. If you would like to create a playlist populated with recordings, each of the track items in the playlist must have an identifier element that contains the MusicBrainz recording that includes the recording MBID. When creating a playlist, only the playlist title and the track identifier elements will be used -- all other elements in the posted JSPF wil be ignored. If a created_for field is found and the user is not an approved playlist bot, then a 403 forbidden will be raised. :reqheader Authorization: Token <user token> :statuscode 200: playlist accepted. :statuscode 400: invalid JSON sent, see error message for details. :statuscode 401: invalid authorization. See error message for details. :statuscode 403: forbidden. The submitting user is not allowed to create playlists for other users. :resheader Content-Type: *application/json* """ user = validate_auth_header() data = request.json validate_create_playlist_required_items(data) validate_playlist(data) public = data["playlist"]["extension"][PLAYLIST_EXTENSION_URI]["public"] collaborators = data.get("playlist", {}).\ get("extension", {}).get(PLAYLIST_EXTENSION_URI, {}).\ get("collaborators", []) # Uniquify collaborators list collaborators = list(set(collaborators)) # Don't allow creator to also be a collaborator if user["musicbrainz_id"] in collaborators: collaborators.remove(user["musicbrainz_id"]) username_lookup = collaborators created_for = data["playlist"].get("created_for", None) if created_for: username_lookup.append(created_for) users = {} if username_lookup: users = db_user.get_many_users_by_mb_id(username_lookup) collaborator_ids = [] for collaborator in collaborators: if collaborator.lower() not in users: log_raise_400("Collaborator {} doesn't exist".format(collaborator)) collaborator_ids.append(users[collaborator.lower()]["id"]) # filter description description = data["playlist"].get("annotation", None) if description is not None: description = _filter_description_html(description) # Check to see if the submitted playlist has algorithm_metadata defined and the current user an approved # playlist submitter; if so, load the metadata from the JSPF playlist and add to the new playlist algorithm_metadata = None if user["musicbrainz_id"] in current_app.config["APPROVED_PLAYLIST_BOTS"]: try: algorithm_metadata = data["playlist"]["extension"][ PLAYLIST_EXTENSION_URI]["algorithm_metadata"] except KeyError: pass playlist = WritablePlaylist(name=data['playlist']['title'], creator_id=user["id"], description=description, collaborator_ids=collaborator_ids, collaborators=collaborators, public=public, algorithm_metadata=algorithm_metadata) if data["playlist"].get("created_for", None): if user["musicbrainz_id"] not in current_app.config[ "APPROVED_PLAYLIST_BOTS"]: raise APIForbidden( "Playlist contains a created_for field, but submitting user is not an approved playlist bot." ) created_for_user = users.get(data["playlist"]["created_for"].lower()) if not created_for_user: log_raise_400("created_for user does not exist.") playlist.created_for_id = created_for_user["id"] if "track" in data["playlist"]: for track in data["playlist"]["track"]: try: playlist.recordings.append( WritablePlaylistRecording(mbid=UUID( track['identifier'][len(PLAYLIST_TRACK_URI_PREFIX):]), added_by_id=user["id"])) except ValueError: log_raise_400( "Invalid recording MBID found in submitted recordings") try: playlist = db_playlist.create(playlist) except Exception as e: current_app.logger.error( "Error while creating new playlist: {}".format(e)) raise APIInternalServerError( "Failed to create the playlist. Please try again.") return jsonify({'status': 'ok', 'playlist_mbid': playlist.mbid})