def load_playlist(playlist_mbid: str): """Load a single playlist by id """ if not is_valid_uuid(playlist_mbid): raise BadRequest("Provided playlist ID is invalid: %s" % playlist_mbid) playlist = db_playlist.get_by_mbid(playlist_mbid, True) # TODO: Allow playlist collaborators to access private playlist if playlist is None or not playlist.public and (not current_user.is_authenticated or playlist.creator_id != current_user.id): raise NotFound("Cannot find playlist: %s" % playlist_mbid) fetch_playlist_recording_metadata(playlist) spotify_data = {} current_user_data = {} if current_user.is_authenticated: spotify_data = spotify.get_user_dict(current_user.id) current_user_data = { "id": current_user.id, "name": current_user.musicbrainz_id, "auth_token": current_user.auth_token, } props = { "current_user": current_user_data, "spotify": spotify_data, "api_url": current_app.config["API_URL"], "web_sockets_server_url": current_app.config['WEBSOCKETS_SERVER_URL'], "playlist": serialize_jspf(playlist) } return render_template( "playlists/playlist.html", props=ujson.dumps(props) )
def playlists(user_name: str): """ Show user playlists """ if not current_app.config.get("FEATURE_PLAYLIST", False): raise NotFound() offset = request.args.get('offset', 0) try: offset = int(offset) except ValueError: raise BadRequest("Incorrect int argument offset: %s" % request.args.get("offset")) count = request.args.get("count", DEFAULT_NUMBER_OF_PLAYLISTS_PER_CALL) try: count = int(count) except ValueError: raise BadRequest("Incorrect int argument count: %s" % request.args.get("count")) user = _get_user(user_name) user_data = { "name": user.musicbrainz_id, "id": user.id, } current_user_data = {} if current_user.is_authenticated: current_user_data = { "id": current_user.id, "name": current_user.musicbrainz_id, "auth_token": current_user.auth_token, } include_private = current_user.is_authenticated and current_user.id == user.id playlists = [] user_playlists, playlist_count = get_playlists_for_user(user.id, include_private=include_private, load_recordings=False, count=count, offset=offset) for playlist in user_playlists: playlists.append(serialize_jspf(playlist)) props = { "current_user": current_user_data, "api_url": current_app.config["API_URL"], "playlists": playlists, "user": user_data, "active_section": "playlists", "playlist_count": playlist_count, "pagination_offset": offset, "playlists_per_page": count, } return render_template( "playlists/playlists.html", active_section="playlists", props=ujson.dumps(props), user=user )
def collaborations(user_name: str): """ Show playlists a user collaborates on """ offset = request.args.get('offset', 0) try: offset = int(offset) except ValueError: raise BadRequest("Incorrect int argument offset: %s" % request.args.get("offset")) count = request.args.get("count", DEFAULT_NUMBER_OF_PLAYLISTS_PER_CALL) try: count = int(count) except ValueError: raise BadRequest("Incorrect int argument count: %s" % request.args.get("count")) user = _get_user(user_name) user_data = { "name": user.musicbrainz_id, "id": user.id, } current_user_data = {} if current_user.is_authenticated: current_user_data = { "id": current_user.id, "name": current_user.musicbrainz_id, "auth_token": current_user.auth_token, } include_private = current_user.is_authenticated and current_user.id == user.id playlists = [] colalborative_playlists, playlist_count = get_playlists_collaborated_on( user.id, include_private=include_private, load_recordings=False, count=count, offset=offset) for playlist in colalborative_playlists: playlists.append(serialize_jspf(playlist)) props = { "current_user": current_user_data, "api_url": current_app.config["API_URL"], "playlists": playlists, "user": user_data, "active_section": "collaborations", "playlist_count": playlist_count, "sentry_dsn": current_app.config.get("LOG_SENTRY", {}).get("dsn") } return render_template("playlists/playlists.html", active_section="collaborations", props=ujson.dumps(props), user=user)
def recommendation_playlists(user_name: str): """ Show playlists created for user """ if not current_app.config.get("FEATURE_PLAYLIST", False): raise NotFound() offset = request.args.get('offset', 0) try: offset = int(offset) except ValueError: raise BadRequest("Incorrect int argument offset: %s" % request.args.get("offset")) count = request.args.get("count", DEFAULT_NUMBER_OF_PLAYLISTS_PER_CALL) try: count = int(count) except ValueError: raise BadRequest("Incorrect int argument count: %s" % request.args.get("count")) user = _get_user(user_name) user_data = { "name": user.musicbrainz_id, "id": user.id, } spotify_data = {} current_user_data = {} if current_user.is_authenticated: spotify_data = spotify.get_user_dict(current_user.id) current_user_data = { "id": current_user.id, "name": current_user.musicbrainz_id, "auth_token": current_user.auth_token, } playlists = [] user_playlists, playlist_count = get_playlists_created_for_user(user.id, False, count, offset) for playlist in user_playlists: playlists.append(serialize_jspf(playlist)) props = { "current_user": current_user_data, "api_url": current_app.config["API_URL"], "playlists": playlists, "user": user_data, "active_section": "recommendations", "playlist_count": playlist_count, } return render_template( "playlists/playlists.html", active_section="recommendations", props=ujson.dumps(props), user=user )
def load_instant(): """ This endpoint takes in a list of recording_mbids and optional desc/name arguments and then loads the recording_mbid's metadata and creates a JSPF file from this data and sends it to the front end so a playlist can be instantly played. .. note:: We recommend that you do not send more than 50 recording_mbids in one request -- our server infrastructure will likely give you a gateway error (502) if you do. :param recording_mbids: A comma separated list of recording_mbids :type recording_mbids: ``str`` :param desc: A description for this instant playlist (optional). :type desc: ``str`` :param name: A name for this instant playlist (optional). :type name: ``str`` :statuscode 200: playlist generated :statuscode 400: invalid recording_mbid arguments """ recordings = request.args.get("recording_mbids", default=None) if recordings is None: raise BadRequest("recording_mbids argument must be present and contain a comma separated list of recording_mbids") recording_mbids = [] for mbid in recordings.split(","): mbid_clean = mbid.strip() if not is_valid_uuid(mbid_clean): raise BadRequest(f"Recording mbid {mbid} is not valid.") recording_mbids.append(mbid_clean) desc = request.args.get("desc", default="") if not desc: desc = "Instant playlist" name = request.args.get("name", default="") if not name: name = "Instant playlist" now = datetime.now() playlist = WritablePlaylist(description=desc, name=name, creator="listenbrainz", creator_id=1, created=now) for i, mbid in enumerate(recording_mbids): rec = WritablePlaylistRecording(position=i, mbid=mbid, added_by_id=1, created=now) playlist.recordings.append(rec) fetch_playlist_recording_metadata(playlist) return render_template( "player/player-page.html", props=ujson.dumps({"playlist": serialize_jspf(playlist)}) )
def serialize_playlists(playlists, playlist_count, count, offset): """ Serialize the playlist metadata for the get playlists commands. """ items = [] for playlist in playlists: items.append(serialize_jspf(playlist)) return {"playlists": items, "playlist_count": playlist_count, "offset": offset, "count": count}
def load_release(release_mbid): """ This endpoint takes a release mbid, loads the tracks for this release and makes a playlist from it and sends it to the front end via JSPF. :statuscode 200: playlist generated :statuscode 400: invalid recording_mbid arguments """ release_mbid = release_mbid.strip() if not is_valid_uuid(release_mbid): raise BadRequest(f"Recording mbid {release_mbid} is not valid.") playlist = None if mb_engine: release = get_release_by_mbid(release_mbid, includes=["media", "artists"]) if not release: raise NotFound("This release was not found in our database. It may not have replicated to this server yet.") name = "Release %s by %s" % (release["name"], release["artist-credit-phrase"]) desc = 'Release <a href="https://musicbrainz.org/release/%s">%s</a> by %s' % (release["mbid"], release["name"], release["artist-credit-phrase"]) now = datetime.now() playlist = WritablePlaylist(description=desc, name=name, creator="listenbrainz", creator_id=1, created=now) for medium in release["medium-list"]: for recording in medium["track-list"]: rec = WritablePlaylistRecording(title=recording["name"], artist_credit=release["artist-credit-phrase"], artist_mbids=[a["artist"]["mbid"] for a in recording["artist-credit"]], release_name=release["name"], release_mbid=release["mbid"], position=recording["position"], mbid=recording["recording_id"], added_by_id=1, created=now) playlist.recordings.append(rec) return render_template( "player/player-page.html", props=ujson.dumps({"playlist": serialize_jspf(playlist) if playlist is not None else {}}) )
def load_playlist(playlist_mbid: str): """Load a single playlist by id """ if not is_valid_uuid(playlist_mbid): raise BadRequest("Provided playlist ID is invalid: %s" % playlist_mbid) current_user_id = None if current_user.is_authenticated: current_user_id = current_user.id playlist = db_playlist.get_by_mbid(playlist_mbid, True) if playlist is None or not playlist.is_visible_by(current_user_id): raise NotFound("Cannot find playlist: %s" % playlist_mbid) fetch_playlist_recording_metadata(playlist) spotify_data = {} current_user_data = {} if current_user.is_authenticated: spotify_data = spotify.get_user_dict(current_user.id) current_user_data = { "id": current_user.id, "name": current_user.musicbrainz_id, "auth_token": current_user.auth_token, } props = { "current_user": current_user_data, "spotify": spotify_data, "api_url": current_app.config["API_URL"], "labs_api_url": current_app.config["LISTENBRAINZ_LABS_API_URL"], "web_sockets_server_url": current_app.config['WEBSOCKETS_SERVER_URL'], "playlist": serialize_jspf(playlist), "sentry_dsn": current_app.config.get("LOG_SENTRY", {}).get("dsn") } return render_template( "playlists/playlist.html", props=ujson.dumps(props) )
def recommendation_playlists(user_name: str): """ Show playlists created for user """ offset = request.args.get('offset', 0) try: offset = int(offset) except ValueError: raise BadRequest("Incorrect int argument offset: %s" % request.args.get("offset")) count = request.args.get("count", DEFAULT_NUMBER_OF_PLAYLISTS_PER_CALL) try: count = int(count) except ValueError: raise BadRequest("Incorrect int argument count: %s" % request.args.get("count")) user = _get_user(user_name) user_data = { "name": user.musicbrainz_id, "id": user.id, } playlists = [] user_playlists, playlist_count = get_playlists_created_for_user( user.id, False, count, offset) for playlist in user_playlists: playlists.append(serialize_jspf(playlist)) props = { "playlists": playlists, "user": user_data, "active_section": "recommendations", "playlist_count": playlist_count, "logged_in_user_follows_user": logged_in_user_follows_user(user), } return render_template("playlists/playlists.html", active_section="recommendations", props=ujson.dumps(props), user=user)
def load_playlist(playlist_mbid: str): """Load a single playlist by id """ if not is_valid_uuid(playlist_mbid): raise BadRequest("Provided playlist ID is invalid: %s" % playlist_mbid) current_user_id = None if current_user.is_authenticated: current_user_id = current_user.id playlist = db_playlist.get_by_mbid(playlist_mbid, True) if playlist is None or not playlist.is_visible_by(current_user_id): raise NotFound("Cannot find playlist: %s" % playlist_mbid) fetch_playlist_recording_metadata(playlist) props = { "labs_api_url": current_app.config["LISTENBRAINZ_LABS_API_URL"], "web_sockets_server_url": current_app.config['WEBSOCKETS_SERVER_URL'], "playlist": serialize_jspf(playlist), } return render_template("playlists/playlist.html", props=ujson.dumps(props))