Exemple #1
0
def get_alerts(user_id, page=1, per_page=None):
    """Return a list of alert objects as a pagination.

    """
    if per_page is None:
        per_page = app.config.get('ALERT_ITEMS_PER_PAGE')

    # Get the last time the users checked the alerts
    # Try and cast the value to an int so we can boolean compare them
    try:
        alerts_last_checked = m.db.users.find_one({
            '_id': user_id
        }).get('alerts_last_checked')
    except (AttributeError, TypeError, ValueError):
        alerts_last_checked = 0

    # Get total number of elements in the sorted set
    total = r.zcard(k.USER_ALERTS.format(user_id))
    aids = r.zrevrange(k.USER_ALERTS.format(user_id), (page - 1) * per_page,
                       (page * per_page) - 1)

    # Create AlertManager to load the alerts
    am = AlertManager()

    alerts = []

    for aid in aids:
        # Load the alert in to the alert manager
        alert = am.get(aid)
        if alert:
            # Check to see if the alert is newer than the time we last checked.
            # This allows us to highlight in the template
            # This will assign a new property to the object: `new`
            if int(alert.timestamp) > alerts_last_checked:
                alert.new = True

            # Add the entire alert from the manager on the list
            alerts.append(alert)
        else:
            # Self cleaning zset
            r.zrem(k.USER_ALERTS.format(user_id), aid)
            total = r.zcard(k.USER_ALERTS.format(user_id))
            # May as well delete the alert if there is one
            r.delete(k.ALERT.format(aid))

    # Update the last time the user checked there alerts
    # This will allow us to alert a user too new alerts with the /i-has-alerts
    # url
    m.db.users.update({'_id': user_id},
                      {'$set': {
                          'alerts_last_checked': timestamp()
                      }})

    return Pagination(alerts, total, page, per_page)
Exemple #2
0
def get_alerts(user_id, page=1, per_page=None):
    """Return a list of alert objects as a pagination.

    """
    if per_page is None:
        per_page = app.config.get('ALERT_ITEMS_PER_PAGE')

    # Get the last time the users checked the alerts
    # Try and cast the value to an int so we can boolean compare them
    try:
        alerts_last_checked = m.db.users.find_one(
            {'_id': user_id}
        ).get('alerts_last_checked')
    except (AttributeError, TypeError, ValueError):
        alerts_last_checked = 0

    # Get total number of elements in the sorted set
    total = r.zcard(k.USER_ALERTS.format(user_id))
    aids = r.zrevrange(k.USER_ALERTS.format(user_id), (page - 1) * per_page,
                       (page * per_page) - 1)

    # Create AlertManager to load the alerts
    am = AlertManager()

    alerts = []

    for aid in aids:
        # Load the alert in to the alert manager
        alert = am.get(aid)
        if alert:
            # Check to see if the alert is newer than the time we last checked.
            # This allows us to highlight in the template
            # This will assign a new property to the object: `new`
            if int(alert.timestamp) > alerts_last_checked:
                alert.new = True

            # Add the entire alert from the manager on the list
            alerts.append(alert)
        else:
            # Self cleaning zset
            r.zrem(k.USER_ALERTS.format(user_id), aid)
            total = r.zcard(k.USER_ALERTS.format(user_id))
            # May as well delete the alert if there is one
            r.delete(k.ALERT.format(aid))

    # Update the last time the user checked there alerts
    # This will allow us to alert a user too new alerts with the /i-has-alerts
    # url
    m.db.users.update({'_id': user_id},
                      {'$set': {'alerts_last_checked': timestamp()}})

    return Pagination(alerts, total, page, per_page)
Exemple #3
0
def get_profile(user_id):
    """Returns a user dict with add post_count, follow_count and following."""
    profile = m.db.users.find_one({'_id': user_id})

    if profile:
        # Count the users posts in MongoDB
        profile['post_count'] = m.db.posts.find(
            {'user_id': user_id, 'reply_to': {'$exists': False}}
        ).count()
        # Count followers and folowees in Redis
        profile['followers_count'] = r.zcard(k.USER_FOLLOWERS.format(user_id))
        profile['following_count'] = r.zcard(k.USER_FOLLOWING.format(user_id))

    return profile if profile else None
Exemple #4
0
    def test_alertmanager(self):
        """
        Test the alert manager.

        Similar to the above a very simple test. Will check that it can alert
        users and one can be created.
        """
        # Create our alert manager
        am = AlertManager()

        # Try and load a non-existant alert
        self.assertIsNone(am.get(k.NIL_VALUE))

        # Try and alert on something which is not an alert
        self.assertRaises(ValueError, lambda: am.alert('ALERT', k.NIL_VALUE))

        # Test that alerting a single users does not work, they need to be
        # iterable
        # Create an alert
        alert = BaseAlert(k.NIL_VALUE)
        self.assertRaises(TypeError, lambda: am.alert(alert, 1))

        # Create a couple of users
        user1 = create_account('user1', '*****@*****.**', 'Password')
        user2 = create_account('user2', '*****@*****.**', 'Password')

        # Ensure the length of user1's alert feed is 0
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user1)), 0)

        # Create an alert from user2
        alert = BaseAlert(user2)
        # Alert user1
        am.alert(alert, [user1])

        # Ensure the length of user1's alert feed is 1
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user1)), 1)

        # Get alerts for user1, user Redis directly
        alerts = r.zrange(k.USER_ALERTS.format(user1), 0, 0)
        # Get the alert from alerts
        alert = am.get(alerts[0])
        self.assertIsNotNone(alert)
        self.assertEqual(alert.user.get('username'), 'user2')
        self.assertEqual(alert.user.get('email'), '*****@*****.**')

        # Delete test2 and ensure getting the alert returns None
        delete_account(user2)
        alert = am.get(alerts[0])
        self.assertIsNone(alert)
Exemple #5
0
    def test_alertmanager(self):
        """
        Test the alert manager.

        Similar to the above a very simple test. Will check that it can alert
        users and one can be created.
        """
        # Create our alert manager
        am = AlertManager()

        # Try and load a non-existant alert
        self.assertIsNone(am.get(k.NIL_VALUE))

        # Try and alert on something which is not an alert
        self.assertRaises(ValueError, lambda: am.alert('ALERT', k.NIL_VALUE))

        # Test that alerting a single users does not work, they need to be
        # iterable
        # Create an alert
        alert = BaseAlert(k.NIL_VALUE)
        self.assertRaises(TypeError, lambda: am.alert(alert, 1))

        # Create a couple of users
        user1 = create_account('user1', '*****@*****.**', 'Password')
        user2 = create_account('user2', '*****@*****.**', 'Password')

        # Ensure the length of user1's alert feed is 0
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user1)), 0)

        # Create an alert from user2
        alert = BaseAlert(user2)
        # Alert user1
        am.alert(alert, [user1])

        # Ensure the length of user1's alert feed is 1
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user1)), 1)

        # Get alerts for user1, user Redis directly
        alerts = r.zrange(k.USER_ALERTS.format(user1), 0, 0)
        # Get the alert from alerts
        alert = am.get(alerts[0])
        self.assertIsNotNone(alert)
        self.assertEqual(alert.user.get('username'), 'user2')
        self.assertEqual(alert.user.get('email'), '*****@*****.**')

        # Delete test2 and ensure getting the alert returns None
        delete_account(user2)
        alert = am.get(alerts[0])
        self.assertIsNone(alert)
Exemple #6
0
def get_profile(user_id):
    """Returns a user dict with add post_count, follow_count and following."""
    profile = m.db.users.find_one({'_id': user_id})

    if profile:
        # Count the users posts in MongoDB
        profile['post_count'] = m.db.posts.find({
            'user_id': user_id,
            'reply_to': {
                '$exists': False
            }
        }).count()
        # Count followers and folowees in Redis
        profile['followers_count'] = r.zcard(k.USER_FOLLOWERS.format(user_id))
        profile['following_count'] = r.zcard(k.USER_FOLLOWING.format(user_id))

    return profile if profile else None
Exemple #7
0
def get_following(uid, page=1):
    """Returns a list of users uid is following as a pagination object."""
    per_page = app.config.get('PROFILE_ITEMS_PER_PAGE')
    total = r.zcard(k.USER_FOLLOWING.format(uid))
    fids = r.zrevrange(k.USER_FOLLOWING.format(uid), (page - 1) * per_page,
                       (page * per_page) - 1)
    users = []
    for fid in fids:
        user = get_user(fid)
        if user:
            users.append(user)
        else:
            # Self cleaning sorted sets
            r.zrem(k.USER_FOLLOWING.format(uid), fid)
            total = r.zcard(k.USER_FOLLOWING.format(id))

    return Pagination(users, total, page, per_page)
Exemple #8
0
def get_following(uid, page=1, per_page=None):
    """Returns a list of users uid is following as a pagination object."""
    if per_page is None:
        per_page = app.config.get('FEED_ITEMS_PER_PAGE')

    total = r.zcard(k.USER_FOLLOWING.format(uid))
    fids = r.zrevrange(k.USER_FOLLOWING.format(uid), (page - 1) * per_page,
                       (page * per_page) - 1)
    users = []
    for fid in fids:
        user = get_user(fid)
        if user:
            users.append(user)
        else:
            # Self cleaning sorted sets
            r.zrem(k.USER_FOLLOWING.format(uid), fid)
            total = r.zcard(k.USER_FOLLOWING.format(id))

    return Pagination(users, total, page, per_page)
Exemple #9
0
def get_followers(uid, page=1, per_page=None):
    """Returns a list of users who follow user with uid as a pagination object.

    """
    if per_page is None:
        per_page = app.config.get('FEED_ITEMS_PER_PAGE')

    total = r.zcard(k.USER_FOLLOWERS.format(uid))
    fids = r.zrevrange(k.USER_FOLLOWERS.format(uid), (page - 1) * per_page,
                       (page * per_page) - 1)
    users = []
    for fid in fids:
        user = get_user(fid)
        if user:
            users.append(user)
        else:
            # Self cleaning sorted sets
            r.zrem(k.USER_FOLLOWERS.format(uid), fid)
            total = r.zcard(k.USER_FOLLOWERS.format(uid))

    return Pagination(users, total, page, per_page)
Exemple #10
0
def get_feed(user_id, page=1):
    """Returns a users feed as a pagination object.

    .. note: The feed is stored inside Redis still as this requires fan-out to
             update all the users who are following you.
    """
    per_page = app.config.get('FEED_ITEMS_PER_PAGE')
    total = r.zcard(k.USER_FEED.format(user_id))
    pids = r.zrevrange(k.USER_FEED.format(user_id), (page - 1) * per_page,
                       (page * per_page) - 1)
    posts = []
    for pid in pids:
        # Get the post
        post = get_post(pid)
        if post:
            posts.append(post)
        else:
            # Self cleaning lists
            r.zrem(k.USER_FEED.format(user_id), pid)
            total = r.zcard(k.USER_FEED.format(user_id))

    return Pagination(posts, total, page, per_page)
Exemple #11
0
def get_feed(user_id, page=1, per_page=None):
    """Returns all the posts in a users feed as a pagination object.

    .. note: The feed is stored inside Redis still as this requires fan-out to
             update all the users who are following you.
    """
    if per_page is None:
        per_page = app.config.get('FEED_ITEMS_PER_PAGE')

    # Get the total number of item in the feed and the subset for the current
    # page.
    total = r.zcard(k.USER_FEED.format(user_id))
    pids = r.zrevrange(k.USER_FEED.format(user_id), (page - 1) * per_page,
                       (page * per_page) - 1)

    # Get all the posts in one call to MongoDB
    posts = []
    cursor = m.db.posts.find({
        '_id': {
            '$in': pids
        }
    }).sort('created', pymongo.DESCENDING)

    for post in cursor:
        posts.append(post)

    # Get a list of unique `user_id`s from all the post.
    user_ids = list(set([post.get('user_id') for post in posts]))
    cursor = m.db.users.find({'_id': {'$in': user_ids}}, {'avatar': True})
    # Create a lookup dict `{username: email}`
    user_avatars = \
        dict((user.get('_id'), user.get('avatar')) for user in cursor)

    # Add the e-mails to the posts
    processed_posts = []
    for post in posts:
        post['user_avatar'] = user_avatars.get(post.get('user_id'))
        processed_posts.append(post)

    # Clean up the list in Redis if the
    if len(processed_posts) < len(pids):
        diff_pids = list(
            set(pids) - set([post.get('_id') for post in processed_posts]))
        r.zrem(k.USER_FEED.format(user_id), *diff_pids)

    return Pagination(processed_posts, total, page, per_page)
Exemple #12
0
def get_feed(user_id, page=1, per_page=None):
    """Returns all the posts in a users feed as a pagination object.

    .. note: The feed is stored inside Redis still as this requires fan-out to
             update all the users who are following you.
    """
    if per_page is None:
        per_page = app.config.get('FEED_ITEMS_PER_PAGE')

    # Get the total number of item in the feed and the subset for the current
    # page.
    total = r.zcard(k.USER_FEED.format(user_id))
    pids = r.zrevrange(k.USER_FEED.format(user_id), (page - 1) * per_page,
                       (page * per_page) - 1)

    # Get all the posts in one call to MongoDB
    posts = []
    cursor = m.db.posts.find({'_id': {'$in': pids}}).sort(
        'created', pymongo.DESCENDING)

    for post in cursor:
        posts.append(post)

    # Get a list of unique `user_id`s from all the post.
    user_ids = list(set([post.get('user_id') for post in posts]))
    cursor = m.db.users.find({'_id': {'$in': user_ids}}, {'avatar': True})
    # Create a lookup dict `{username: email}`
    user_avatars = \
        dict((user.get('_id'), user.get('avatar')) for user in cursor)

    # Add the e-mails to the posts
    processed_posts = []
    for post in posts:
        post['user_avatar'] = user_avatars.get(post.get('user_id'))
        processed_posts.append(post)

    # Clean up the list in Redis if the
    if len(processed_posts) < len(pids):
        diff_pids = list(
            set(pids) - set([post.get('_id') for post in processed_posts]))
        r.zrem(k.USER_FEED.format(user_id), *diff_pids)

    return Pagination(processed_posts, total, page, per_page)
Exemple #13
0
    def test_alerts(self):
        """
        Tests for the 2 functions which are used on the side to get alerts and
        also test FollowAlert from here.
        """
        # Create 2 test users
        user1 = create_account('user1', '*****@*****.**', 'Password')
        user2 = create_account('user2', '*****@*****.**', 'Password')

        # Ensure that get_alerts pagination object is empty
        self.assertEqual(get_alerts(user1).total, 0)
        self.assertEqual(len(get_alerts(user1).items), 0)

        # Get user 2 to follow user 1
        follow_user(user2, user1)

        # Check that i_has_alerts is True
        self.assertTrue(new_alerts(user1))

        # Ensure that there is an alert in the get_alerts
        self.assertEqual(get_alerts(user1).total, 1)
        self.assertEqual(len(get_alerts(user1).items), 1)

        # Check that i_has_alerts is False, we have read them with get_alerts
        self.assertFalse(new_alerts(user1))

        # Get the alert and check that the alert is the follow alert
        alert = get_alerts(user1).items[0]
        self.assertTrue(isinstance(alert, FollowAlert))
        # Also check it's still a BaseAlert
        self.assertTrue(isinstance(alert, BaseAlert))
        # Check its from test2
        self.assertEqual(alert.user.get('username'), 'user2')
        self.assertEqual(alert.user.get('email'), '*****@*****.**')
        self.assertIn('has started following you', alert.prettify())

        # Delete test2 and ensure we get no alerts
        delete_account(user2)

        # Ensure the alert is still inside Redis
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user1)), 1)

        # Get the alerts, should be none and should also clear the alert from
        # Redis
        self.assertEqual(get_alerts(user1).total, 0)
        self.assertEqual(len(get_alerts(user1).items), 0)
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user1)), 0)

        # Do the same as above to ensure we can delete an alert ourselves
        # Create another user
        user3 = create_account('user3', '*****@*****.**', 'Password')

        follow_user(user1, user3)

        # Check the alerts are there
        alert = get_alerts(user3).items[0]
        self.assertTrue(isinstance(alert, FollowAlert))
        # Also check it's still a BaseAlert
        self.assertTrue(isinstance(alert, BaseAlert))
        # Check its from test2
        self.assertEqual(alert.user.get('username'), 'user1')
        self.assertEqual(alert.user.get('email'), '*****@*****.**')
        self.assertIn('has started following you', alert.prettify())

        # Delete the alert with aid from the alert
        delete_alert(user3, alert.alert_id)

        # Get the alerts and ensure the list is empty
        self.assertEqual(get_alerts(user3).total, 0)
        self.assertEqual(len(get_alerts(user3).items), 0)
        self.assertEqual(r.zcard(k.USER_ALERTS.format(user3)), 0)

        # Unfollow the user3 and then follow them again
        unfollow_user(user1, user3)
        follow_user(user1, user3)

        alert = get_alerts(user3).items[0]
        self.assertIn('has started following you', alert.prettify())

        # Manually delete the alert
        r.delete(k.ALERT.format(alert.alert_id))

        # Get the alerts again and ensure the length is 0
        # Ensure that the alert is not pulled down
        alerts = get_alerts(user3)
        self.assertEqual(len(alerts.items), 0)

        # Get alerts for a non-existant user
        # This will not fail but will have an empty pagination
        alerts = get_alerts(k.NIL_VALUE)
        self.assertEqual(len(alerts.items), 0)