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)
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
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)
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