def get_recording_pin_events(users_for_events: List[dict], min_ts: int,
                             max_ts: int,
                             count: int) -> List[APITimelineEvent]:
    """ Gets all recording pin events in the feed."""

    id_username_map = {
        user['id']: user['musicbrainz_id']
        for user in users_for_events
    }
    recording_pin_events_db = get_pins_for_feed(
        user_ids=(user['id'] for user in users_for_events),
        min_ts=min_ts,
        max_ts=max_ts,
        count=count,
    )
    recording_pin_events_db = fetch_track_metadata_for_pins(
        recording_pin_events_db)

    events = []
    for pin in recording_pin_events_db:
        try:
            pinEvent = APIPinEvent(
                user_name=id_username_map[pin.user_id],
                blurb_content=pin.blurb_content,
                track_metadata=TrackMetadata(
                    artist_name=pin.track_metadata["artist_name"],
                    track_name=pin.track_metadata["track_name"],
                    release_name=None,
                    additional_info=AdditionalInfo(
                        recording_msid=pin.recording_msid,
                        recording_mbid=pin.recording_mbid,
                        artist_msid=pin.track_metadata["artist_msid"],
                    )))
            events.append(
                APITimelineEvent(
                    event_type=UserTimelineEventType.RECORDING_PIN,
                    user_name=pinEvent.user_name,
                    created=pin.created.timestamp(),
                    metadata=pinEvent,
                ))
        except pydantic.ValidationError as e:
            current_app.logger.error('Validation error: ' + str(e),
                                     exc_info=True)
            continue
    return events
示例#2
0
def pins(user_name: str):
    """ Show user pin history """

    user = _get_user(user_name)
    user_data = {
        "name": user.musicbrainz_id,
        "id": user.id,
    }

    pins = get_pin_history_for_user(user_id=user.id, count=25, offset=0)
    pins = [dict(pin) for pin in fetch_track_metadata_for_pins(pins)]
    total_count = get_pin_count_for_user(user_id=user.id)

    props = {
        "user": user_data,
        "pins": pins,
        "profile_url": url_for('user.profile', user_name=user_name),
        "total_count": total_count
    }

    return render_template("user/pins.html",
                           active_section="pins",
                           props=ujson.dumps(props),
                           user=user)
def get_pins_for_user_following(user_name):
    """
    Get a list containing the active pinned recordings for all users in a user's ``user_name``
    following list. The returned pinned recordings are sorted in descending order of the time they were pinned.
    The JSON returned by the API will look like the following:

    .. code-block:: json

        {
            "count": 1,
            "offset": 0,
            "pinned_recordings": [
                {
                "blurb_content": "Spectacular recording!",
                "created": 1624000841,
                "row_id": 1,
                "pinned_until": 1624605641,
                "recording_mbid": null,
                "recording_msid": "40ef0ae1-5626-43eb-838f-1b34187519bf",
                "track_metadata": {
                        "artist_msid": "8c7b4641-e363-4598-ae70-7709840fb934",
                        "artist_name": "Rick Astley",
                        "track_name": "Never Gonna Give You Up"
                },
                "user_name": "-- the MusicBrainz ID of the user who pinned this recording --"
                },
                "-- more pinned recordings from different users here ---"
            ],
            "user_name": "-- the MusicBrainz ID of the original user --"
        }

    :param user_name: the MusicBrainz ID of the user whose followed user's pinned recordings are being requested.
    :type user_name: ``str``
    :param count: Optional, number of pinned recording items to return,
        Default: :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET`
        Max: :data:`~webserver.views.api.MAX_ITEMS_PER_GET`
    :type count: ``int``
    :param offset: Optional, number of pinned recording items to skip from the beginning, for pagination.
        Ex. An offset of 5 means the most recent pinned recordings from the first 5 users will be skipped, defaults to 0
    :type offset: ``int``
    :statuscode 200: Yay, you have data!
    :statuscode 400: Invalid query parameters. See error message for details.
    :statuscode 404: The requested user was not found.
    :resheader Content-Type: *application/json*
    """

    count = get_non_negative_param("count", default=DEFAULT_ITEMS_PER_GET)
    offset = get_non_negative_param("offset", default=0)

    count = min(count, MAX_ITEMS_PER_GET)

    user = db_user.get_by_mb_id(user_name)
    if user is None:
        raise APINotFound("Cannot find user: %s" % user_name)

    pinned_recordings = db_pinned_rec.get_pins_for_user_following(
        user_id=user["id"], count=count, offset=offset)
    pinned_recordings = fetch_track_metadata_for_pins(pinned_recordings)
    pinned_recordings = [
        _pinned_recording_to_api(pin) for pin in pinned_recordings
    ]

    return jsonify({
        "pinned_recordings": pinned_recordings,
        "count": len(pinned_recordings),
        "offset": offset,
        "user_name": user_name,
    })
def get_pins_for_user(user_name):
    """
    Get a list of all recordings ever pinned by a user with given ``user_name`` in descending order of the time
    they were originally pinned. The JSON returned by the API will look like the following:

    .. code-block:: json

        {
            "count": 10,
            "offset": 0,
            "pinned_recordings": [
                {
                    "blurb_content": "Awesome recording!",
                    "created": 1623997168,
                    "row_id": 10,
                    "pinned_until": 1623997485,
                    "recording_mbid": null,
                    "recording_msid": "fd7d9162-a284-4a10-906c-faae4f1e166b"
                    "track_metadata": {
                        "artist_msid": "8c7b4641-e363-4598-ae70-7709840fb934",
                        "artist_name": "Rick Astley",
                        "track_name": "Never Gonna Give You Up"
                        }
                },
                "-- more pinned recording items here ---"
            ],
            "total_count": 10,
            "user_name": "-- the MusicBrainz ID of the user --"
        }

    :param user_name: the MusicBrainz ID of the user whose pin track history requested.
    :type user_name: ``str``
    :param count: Optional, number of pinned recording items to return,
        Default: :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET`
        Max: :data:`~webserver.views.api.MAX_ITEMS_PER_GET`
    :type count: ``int``
    :param offset: Optional, number of pinned recording items to skip from the beginning, for pagination.
        Ex. An offset of 5 means the most recent 5 pinned recordings from the user will be skipped, defaults to 0
    :type offset: ``int``
    :statuscode 200: Yay, you have data!
    :statuscode 400: Invalid query parameters. See error message for details.
    :statuscode 404: The requested user was not found.
    :resheader Content-Type: *application/json*
    """
    offset = get_non_negative_param("offset", default=0)
    count = get_non_negative_param("count", default=DEFAULT_ITEMS_PER_GET)

    count = min(count, MAX_ITEMS_PER_GET)

    user = db_user.get_by_mb_id(user_name)
    if user is None:
        raise APINotFound("Cannot find user: %s" % user_name)

    try:
        pinned_recordings = db_pinned_rec.get_pin_history_for_user(
            user_id=user["id"], count=count, offset=offset)
    except Exception as e:
        current_app.logger.error(
            "Error while retrieving pins for user: {}".format(e))
        raise APIInternalServerError("Something went wrong. Please try again.")

    pinned_recordings = fetch_track_metadata_for_pins(pinned_recordings)
    pinned_recordings = [
        _pinned_recording_to_api(pin) for pin in pinned_recordings
    ]
    total_count = db_pinned_rec.get_pin_count_for_user(user_id=user["id"])

    return jsonify({
        "pinned_recordings": pinned_recordings,
        "total_count": total_count,
        "count": len(pinned_recordings),
        "offset": offset,
        "user_name": user_name,
    })
示例#5
0
def profile(user_name):
    # Which database to use to showing user listens.
    db_conn = webserver.timescale_connection._ts
    # Which database to use to show playing_now stream.
    playing_now_conn = webserver.redis_connection._redis

    user = _get_user(user_name)
    # User name used to get user may not have the same case as original user name.
    user_name = user.musicbrainz_id

    # Getting data for current page
    max_ts = request.args.get("max_ts")
    if max_ts is not None:
        try:
            max_ts = int(max_ts)
        except ValueError:
            raise BadRequest("Incorrect timestamp argument max_ts: %s" %
                             request.args.get("max_ts"))

    min_ts = request.args.get("min_ts")
    if min_ts is not None:
        try:
            min_ts = int(min_ts)
        except ValueError:
            raise BadRequest("Incorrect timestamp argument min_ts: %s" %
                             request.args.get("min_ts"))

    args = {}
    if max_ts:
        args['to_ts'] = max_ts
    else:
        args['from_ts'] = min_ts
    data, min_ts_per_user, max_ts_per_user = db_conn.fetch_listens(
        user_name, limit=LISTENS_PER_PAGE, **args)

    listens = []
    for listen in data:
        listens.append(listen.to_api())

    # If there are no previous listens then display now_playing
    if not listens or listens[0]['listened_at'] >= max_ts_per_user:
        playing_now = playing_now_conn.get_playing_now(user.id)
        if playing_now:
            listen = {
                "track_metadata": playing_now.data,
                "playing_now": "true",
            }
            listens.insert(0, listen)

    user_stats = db_stats.get_user_stats(user.id, 'all_time', 'artists')

    logged_in_user_follows_user = None
    already_reported_user = False
    if current_user.is_authenticated:
        logged_in_user_follows_user = db_user_relationship.is_following_user(
            current_user.id, user.id)
        already_reported_user = db_user.is_user_reported(
            current_user.id, user.id)

    pin = get_current_pin_for_user(user_id=user.id)
    if pin:
        pin = dict(fetch_track_metadata_for_pins([pin])[0])

    props = {
        "user": {
            "id": user.id,
            "name": user.musicbrainz_id,
        },
        "listens": listens,
        "latest_listen_ts": max_ts_per_user,
        "oldest_listen_ts": min_ts_per_user,
        "latest_spotify_uri": _get_spotify_uri_for_listens(listens),
        "artist_count": format(user_stats.count, ",d") if user_stats else None,
        "profile_url": url_for('user.profile', user_name=user_name),
        "mode": "listens",
        "userPinnedRecording": pin,
        "web_sockets_server_url": current_app.config['WEBSOCKETS_SERVER_URL'],
        "logged_in_user_follows_user": logged_in_user_follows_user,
        "already_reported_user": already_reported_user,
    }

    return render_template("user/profile.html",
                           props=ujson.dumps(props),
                           mode='listens',
                           user=user,
                           active_section='listens')