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, }})
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"]})
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})
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], } })