Exemple #1
0
    def test_get_following_for_user_returns_correct_data(self):

        # no relationships yet, should return an empty list
        following = db_user_relationship.get_following_for_user(
            self.main_user['id'])
        self.assertListEqual(following, [])

        # make the main_user follow followed_user_1
        db_user_relationship.insert(self.main_user['id'],
                                    self.followed_user_1['id'], 'follow')

        # the list of users main_user is following should have 1 element now
        following = db_user_relationship.get_following_for_user(
            self.main_user['id'])
        self.assertEqual(1, len(following))

        # make it so that the main user follows two users, followed_user_1 and followed_user_2
        self.followed_user_2 = db_user.get_or_create(3, 'followed_user_2')
        db_user_relationship.insert(self.main_user['id'],
                                    self.followed_user_2['id'], 'follow')

        # the list of users main_user is following should have 2 elements now
        following = db_user_relationship.get_following_for_user(
            self.main_user['id'])
        self.assertEqual(2, len(following))
def user_feed(user_name: str):
    db_conn = webserver.create_timescale(current_app)
    min_ts, max_ts, count, time_range = _validate_get_endpoint_params(db_conn, user_name)
    if min_ts is None and max_ts is None:
        max_ts = int(time.time())

    user = db_user.get_by_mb_id(user_name)
    if not user:
        raise APINotFound(f"User {user_name} not found")

    users_following = [user['musicbrainz_id'] for user in db_user_relationship.get_following_for_user(user['id'])]

    listens = db_conn.fetch_listens_for_multiple_users_from_storage(
        users_following,
        limit=count,
        from_ts=min_ts,
        to_ts=max_ts,
        time_range=time_range,
        order=1,  # descending
    )
    listen_data = []
    for listen in listens:
        listen_data.append(listen.to_api())

    return jsonify({'payload': {
        'user_id': user_name,
        'count': len(listen_data),
        'feed': listen_data,
    }})
Exemple #3
0
def get_following(user_name: str):
    """
    Fetch the list of users followed by the user ``user_name``. Returns a JSON with an array of user names like these:

    .. code-block:: json

        {
            "followers": ["rob", "mr_monkey", "..."],
            "user": "******"
        }

    :statuscode 200: Yay, you have data!
    :statuscode 404: User not found
    """
    user = db_user.get_by_mb_id(user_name)

    if not user:
        raise APINotFound("User %s not found" % user_name)

    try:
        following = db_user_relationship.get_following_for_user(user["id"])
        following = [user["musicbrainz_id"] for user in following]
    except Exception as e:
        current_app.logger.error("Error while trying to fetch following: %s",
                                 str(e))
        raise APIInternalServerError(
            "Something went wrong, please try again later")

    return jsonify({"following": following, "user": user["musicbrainz_id"]})
Exemple #4
0
def get_following(user_name: str):
    user = _get_user(user_name)
    try:
        following = db_user_relationship.get_following_for_user(user.id)
    except Exception:
        current_app.logger.critical("Error while trying to fetch following", exc_info=True)
        raise APIInternalServerError("Something went wrong, please try again later")

    return jsonify({"following": following, "user": user.musicbrainz_id})
Exemple #5
0
def user_feed(user_name: str):
    """ Get feed events for a user's timeline.

    :param user_name: The MusicBrainz ID of the user whose timeline is being requested.
    :type user_name: ``str``
    :param max_ts: If you specify a ``max_ts`` timestamp, events with timestamps less than the value will be returned
    :param min_ts: If you specify a ``min_ts`` timestamp, events with timestamps greater than the value will be returned
    :param count: Optional, number of events to return. Default: :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET` . Max: :data:`~webserver.views.api.MAX_ITEMS_PER_GET`
    :statuscode 200: Successful query, you have feed events!
    :statuscode 400: Bad request, check ``response['error']`` for more details.
    :statuscode 401: Unauthorized, you do not have permission to view this user's feed.
    :statuscode 404: User not found
    :resheader Content-Type: *application/json*
    """

    user = validate_auth_header()
    if user_name != user['musicbrainz_id']:
        raise APIUnauthorized(
            "You don't have permissions to view this user's timeline.")

    db_conn = webserver.create_timescale(current_app)
    min_ts, max_ts, count, time_range = _validate_get_endpoint_params(
        db_conn, user_name)
    if min_ts is None and max_ts is None:
        max_ts = int(time.time())

    users_following = db_user_relationship.get_following_for_user(user['id'])

    # get all listen events
    musicbrainz_ids = [user['musicbrainz_id'] for user in users_following]
    if len(users_following) == 0:
        listen_events = []
    else:
        listen_events = get_listen_events(db_conn, musicbrainz_ids, min_ts,
                                          max_ts, count, time_range)

    # for events like "follow" and "recording recommendations", we want to show the user
    # their own events as well
    users_for_feed_events = users_following + [user]
    follow_events = get_follow_events(
        user_ids=tuple(user['id'] for user in users_for_feed_events),
        min_ts=min_ts or 0,
        max_ts=max_ts or int(time.time()),
        count=count,
    )

    recording_recommendation_events = get_recording_recommendation_events(
        users_for_events=users_for_feed_events,
        min_ts=min_ts or 0,
        max_ts=max_ts or int(time.time()),
        count=count,
    )

    notification_events = get_notification_events(user, count)

    # TODO: add playlist event and like event
    all_events = sorted(listen_events + follow_events +
                        recording_recommendation_events + notification_events,
                        key=lambda event: -event.created)

    # sadly, we need to serialize the event_type ourselves, otherwise, jsonify converts it badly
    for index, event in enumerate(all_events):
        all_events[index].event_type = event.event_type.value

    all_events = all_events[:count]

    return jsonify({
        'payload': {
            'count': len(all_events),
            'user_id': user_name,
            'events': [event.dict() for event in all_events],
        }
    })