def edit_playlist(playlist_mbid): """ Edit the private/public status, name, description or list of collaborators for an exising playlist. The Authorization header must be set and correspond to the owner of the playlist otherwise a 403 error will be returned. All fields will be overwritten with new values. :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 subitting user is not allowed to edit playlists for other users. :resheader Content-Type: *application/json* """ user = validate_auth_header() data = request.json validate_playlist(data) if not is_valid_uuid(playlist_mbid): log_raise_400("Provided playlist ID is invalid.") playlist = db_playlist.get_by_mbid(playlist_mbid, False) if playlist is None or not playlist.is_visible_by(user["id"]): raise APINotFound("Cannot find playlist: %s" % playlist_mbid) if playlist.creator_id != user["id"]: raise APIForbidden("You are not allowed to edit this playlist.") try: playlist.public = data["playlist"]["extension"][PLAYLIST_EXTENSION_URI]["public"] except KeyError: pass if "annotation" in data["playlist"]: # If the annotation key exists but the value is empty ("" or None), # unset the description description = data["playlist"]["annotation"] if description: description = _filter_description_html(description) else: description = None playlist.description = description if data["playlist"].get("title"): playlist.name = data["playlist"]["title"] collaborators = data.get("playlist", {}).\ get("extension", {}).get(PLAYLIST_EXTENSION_URI, {}).\ get("collaborators", []) users = {} # 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"]) if collaborators: users = db_user.get_many_users_by_mb_id(collaborators) 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"]) playlist.collaborators = collaborators playlist.collaborator_ids = collaborator_ids db_playlist.update_playlist(playlist) 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) playlist = WritablePlaylist(name=data['playlist']['title'], creator_id=user["id"], description=description, collaborator_ids=collaborator_ids, collaborators=collaborators, public=public) 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})