예제 #1
0
 def get_matching_friends(self):
     user = current_user._get_current_object()
     name_search = request.args.get('name__icontains')
     # note: it's 3x faster to perform one call vs. `FBF.objects().filter()`
     if name_search:
         return FacebookFriend.objects(user=user, name_uppercase__contains=name_search.upper())
     else:
         return FacebookFriend.objects(user=user)
예제 #2
0
def top_friends_task(user_id):
    """
    Pulls all friends and all photo tags, combines them
    to get `top_friends_score` and saves to the `User.friends` field
    """
    # Run the child tasks
    friends_task =          run_fql.s(task_cls=GetFriendsTask, user_id=user_id)
    tagged_with_me_task =   run_fql.s(task_cls=TaggedWithMeTask, user_id=user_id)
    job_async = group([friends_task, tagged_with_me_task]).apply_async()

    results = job_async.get()
    results = merge_dicts(*results)

    all_friends = results['get_friends']
    tagged_with_me = results['tagged_with_me']

    # Collapse the tags by user_id, discount by age
    tag_score_by_user_id = defaultdict(lambda: 0.0)
    for tag in tagged_with_me.fields:
        tag_age = datetime.date.today().year - tag['created'].year + 1.0
        tag_score_by_user_id[tag['subject']] += 1 / tag_age

    # Sort
    user_ids_in_score_order = sorted(tag_score_by_user_id.items(), key=lambda x: x[1])

    # Reversing them means the index corresponds to top friends order
    top_friends_order_by_id = {}
    for top_friends_order, u in enumerate(user_ids_in_score_order):
        top_friends_order_by_id[u[0]] = top_friends_order + 1   # 0 is not a valid value

    # Copy `top_friends_order`s to `all_friends`
    for id, top_friends_order in top_friends_order_by_id.items():
        try:
            all_friends.fields_by_id[id]['top_friends_order'] = top_friends_order
        except KeyError:
            # Means you were tagged with someone you aren't friends with
            pass

    # Save
    user = User.objects.get(id=user_id)
    # Clear current friends
    FacebookFriend.objects(user=user).delete()
    # Bulk insert the new ones
    docs = []
    for friend in results['get_friends'].fields:
        uid = friend.pop('id')
        docs.append(FacebookFriend(uid=uid, user=user, **friend))
    FacebookFriend.objects.insert(docs)

    logger.info('Pulled %d friends, %d top friends for user %s'
                % (len(all_friends), len(top_friends_order_by_id), user.get_id_str()))

    return results
예제 #3
0
 def get_queryset(self):
     # User models having those ids
     friend_ids_in_app = self.get_friend_ids_in_app()
     # Friend models with those ids
     return FacebookFriend.objects(uid__nin=friend_ids_in_app)
예제 #4
0
def calculate_top_friends(user, book,
                          others_posts_from_year, owner_posts_from_year, db_photos_by_id,
                          photos_of_me, comments_score_by_user_id):

    # Combine the lists of posts
    all_posts_this_year = ResultGetter.from_fields(itertools.chain(
        others_posts_from_year,
        owner_posts_from_year
    ))

    # Strip posts that have an attachment that is a photo?
    #    .filter(lambda x: 'attachment' in x and 'fb_object_type' in x['attachment'] and x['attachment'])

    # Assign each friend points for each post they made
    posts_score_by_user_id = defaultdict(lambda: 0)
    for post in all_posts_this_year:
        # if 'score' not in post:
        #     post['score'] = 0
        # post['score'] += TOP_FRIEND_POINTS_FOR_POST
        posts_score_by_user_id[post['actor_id']] += TOP_FRIEND_POINTS_FOR_POST

    # Calculate photo score for each user, discounted by year
    photos_score_by_user_id = defaultdict(lambda: 0.0)
    # tagged_friends = FacebookFriend.objects(user=user, book=book, tagged_in_photos__exists=True)    # they have at least one tag
    for friend in book.friends:
        for tag in friend.tagged_in_photos:
            photo_id = tag['object_id']
            peeps_in_photo = db_photos_by_id[photo_id].num_people_in_photo
            photo = photos_of_me.fields_by_id[photo_id]
            #            photo_age = 2012 - photo['created'].year + 1.0
            photo_age = datetime.date.today().year - photo['created'].year + 1.0
            if peeps_in_photo == 2:
                photos_score_by_user_id[friend.uid] += TOP_FRIEND_POINTS_FOR_PHOTO_OF_2 / photo_age
            elif peeps_in_photo == 3:
                photos_score_by_user_id[friend.uid] += TOP_FRIEND_POINTS_FOR_PHOTO_OF_3 / photo_age
            elif peeps_in_photo >= 4:
                photos_score_by_user_id[friend.uid] += TOP_FRIEND_POINTS_FOR_PHOTO_OF_4 / photo_age

    # Add em up
    top_friend_ids = (set(comments_score_by_user_id.keys()) | set(posts_score_by_user_id.keys())
                      | set(photos_score_by_user_id))
    top_friend_ids.remove(user.profile.facebook_id)

    # Tag the users in the database and update their score
    for user_id in top_friend_ids:
        FacebookFriend.objects(book=book, uid=user_id).update(
            top_friends_score=comments_score_by_user_id[user_id] + posts_score_by_user_id[user_id]
                              + photos_score_by_user_id[user_id],
            comments_score=comments_score_by_user_id[user_id],
            posts_score=posts_score_by_user_id[user_id],
            photos_score=photos_score_by_user_id[user_id],
            tags__push=TOP_FRIEND_TAG
        )

    # Grab the top 20 users and give them an additional tag
    for top_20_user in book.friends.order_by('-top_friends_score')[:20]:
        top_20_user.update(tags__push=TOP_20_FRIEND_TAG)

    # Cache a list of the friends by id
    db_friends_by_id = {friend.uid: friend for friend in book.friends}

    results = {
        'all_posts_this_year': all_posts_this_year,
        'db_friends_by_id': db_friends_by_id,
    }
    return results