def authenticate(self, facebook_id=None, facebook_email=None): ''' Authenticate the facebook user by id OR facebook_email We filter using an OR to allow existing members to connect with their facebook ID using email. ''' if facebook_id or facebook_email: profile_class = get_profile_class() profile_query = profile_class.objects.all().order_by('user') profile_query = profile_query.select_related('user') profile = None #filter on email or facebook id, two queries for better #queryplan with large data sets if facebook_id: profiles = profile_query.filter(facebook_id=facebook_id)[:1] profile = profiles[0] if profiles else None if profile is None and facebook_email: try: profiles = profile_query.filter( user__email__iexact=facebook_email)[:1] profile = profiles[0] if profiles else None except DatabaseError: try: user = models.User.objects.get(email=facebook_email) except models.User.DoesNotExist: user = None profile = user.get_profile() if user else None if profile: # populate the profile cache while we're getting it anyway user = profile.user user._profile = profile return user
def test_user_registered_signal(self): # Ensure user registered, pre update and post update signals fire def user_registered(sender, user, facebook_data, **kwargs): user.registered_signal = True def pre_update(sender, profile, facebook_data, **kwargs): profile.pre_update_signal = True def post_update(sender, profile, facebook_data, **kwargs): profile.post_update_signal = True Profile = get_profile_class() signals.facebook_user_registered.connect(user_registered, sender=User) signals.facebook_pre_update.connect(pre_update, sender=Profile) signals.facebook_post_update.connect(post_update, sender=Profile) graph = get_facebook_graph(access_token='short_username') facebook = FacebookUserConverter(graph) user = _register_user(self.request, facebook) self.assertEqual(hasattr(user, 'registered_signal'), True) self.assertEqual(hasattr(user.get_profile(), 'pre_update_signal'), True) self.assertEqual(hasattr(user.get_profile(), 'post_update_signal'), True)
def random_facebook_friends(self, user, gender=None, limit=3): ''' Returns a random sample of your FB friends Limit = Number of friends Gender = None, M or F ''' assert gender in (None, 'M', 'F'), 'Gender %s wasnt recognized' % gender from greenroom.apps.django_facebook_patched.utils import get_profile_class facebook_cache_key = 'facebook_users_%s' % user.id non_members = cache.get(facebook_cache_key) profile_class = get_profile_class() if not non_members: facebook_users = list(self.filter(user_id=user.id, gender=gender)[:50]) facebook_ids = [u.facebook_id for u in facebook_users] members = list(profile_class.objects.filter(facebook_id__in=facebook_ids).select_related('user')) member_ids = [p.facebook_id for p in members] non_members = [u for u in facebook_users if u.facebook_id not in member_ids] cache.set(facebook_cache_key, non_members, 60*60) random_limit = min(len(non_members), 3) random_facebook_users = [] if random_limit: random_facebook_users = random.sample(non_members, random_limit) return random_facebook_users
def _store_likes(self, user, likes): current_likes = inserted_likes = None if likes: from greenroom.apps.django_facebook_patched.models import FacebookLike base_queryset = FacebookLike.objects.filter(user_id=user.id) global_defaults = dict(user_id=user.id) id_field = 'facebook_id' default_dict = {} for like in likes: name = like.get('name') created_time_string = like.get('created_time') created_time = None if created_time_string: created_time = datetime.datetime.strptime( like['created_time'], "%Y-%m-%dT%H:%M:%S+0000") default_dict[like['id']] = dict( created_time=created_time, category=like.get('category'), name=name ) current_likes, inserted_likes = mass_get_or_create( FacebookLike, base_queryset, id_field, default_dict, global_defaults) logger.debug('found %s likes and inserted %s new likes', len(current_likes), len(inserted_likes)) #fire an event, so u can do things like personalizing the users' account #based on the likes signals.facebook_post_store_likes.send(sender=get_profile_class(), user=user, likes=likes, current_likes=current_likes, inserted_likes=inserted_likes, ) return likes
def _remove_old_connections(facebook_id, current_user_id=None): ''' Removes the facebook id for profiles with the specified facebook id which arent the current user id ''' profile_class = get_profile_class() other_facebook_accounts = profile_class.objects.filter( facebook_id=facebook_id) if current_user_id: other_facebook_accounts = other_facebook_accounts.exclude( user__id=current_user_id) other_facebook_accounts.update(facebook_id=None)
def registered_friends(self, user): ''' Returns all profile models which are already registered on your site and a list of friends which are not on your site ''' from greenroom.apps.django_facebook_patched.utils import get_profile_class profile_class = get_profile_class() friends = self.get_friends(limit=1000) if friends: friend_ids = [f['id'] for f in friends] friend_objects = profile_class.objects.filter( facebook_id__in=friend_ids).select_related('user') registered_ids = [f.facebook_id for f in friend_objects] new_friends = [f for f in friends if f['id'] not in registered_ids] else: new_friends = [] friend_objects = profile_class.objects.none() return friend_objects, new_friends
def _store_friends(self, user, friends): from greenroom.apps.django_facebook_patched.models import FacebookUser current_friends = inserted_friends = None #store the users for later retrieval if friends: #see which ids this user already stored base_queryset = FacebookUser.objects.filter(user_id=user.id) #if none if your friend have a gender clean the old data genders = FacebookUser.objects.filter(user_id=user.id, gender__in=('M','F')).count() if not genders: FacebookUser.objects.filter(user_id=user.id).delete() global_defaults = dict(user_id=user.id) default_dict = {} gender_map = dict(female='F', male='M') for f in friends: name = f.get('name') gender = None if f.get('sex'): gender = gender_map[f.get('sex')] default_dict[str(f['id'])] = dict(name=name, gender=gender) id_field = 'facebook_id' current_friends, inserted_friends = mass_get_or_create( FacebookUser, base_queryset, id_field, default_dict, global_defaults) logger.debug('found %s friends and inserted %s new ones', len(current_friends), len(inserted_friends)) #fire an event, so u can do things like personalizing suggested users #to follow signals.facebook_post_store_friends.send(sender=get_profile_class(), user=user, friends=friends, current_friends=current_friends, inserted_friends=inserted_friends, ) return friends
def _update_user(user, facebook, overwrite=True): ''' Updates the user and his/her profile with the data from facebook ''' # if you want to add fields to ur user model instead of the # profile thats fine # partial support (everything except raw_data and facebook_id is included) facebook_data = facebook.facebook_registration_data(username=False) facebook_fields = ['facebook_name', 'facebook_profile_url', 'gender', 'date_of_birth', 'about_me', 'website_url', 'first_name', 'last_name'] user_dirty = profile_dirty = False profile = user.get_profile() signals.facebook_pre_update.send(sender=get_profile_class(), profile=profile, facebook_data=facebook_data) profile_field_names = [f.name for f in profile._meta.fields] user_field_names = [f.name for f in user._meta.fields] #set the facebook id and make sure we are the only user with this id facebook_id_changed = facebook_data['facebook_id'] != profile.facebook_id overwrite_allowed = overwrite or not profile.facebook_id #update the facebook id and access token if facebook_id_changed and overwrite_allowed: #when not overwriting we only update if there is no profile.facebook_id logger.info('profile facebook id changed from %s to %s', repr(facebook_data['facebook_id']), repr(profile.facebook_id)) profile.facebook_id = facebook_data['facebook_id'] profile_dirty = True _remove_old_connections(profile.facebook_id, user.id) #update all fields on both user and profile for f in facebook_fields: facebook_value = facebook_data.get(f, False) if facebook_value: if (f in profile_field_names and hasattr(profile, f) and not getattr(profile, f, False)): logger.debug('profile field %s changed from %s to %s', f, getattr(profile, f), facebook_value) setattr(profile, f, facebook_value) profile_dirty = True elif (f in user_field_names and hasattr(user, f) and not getattr(user, f, False)): logger.debug('user field %s changed from %s to %s', f, getattr(user, f), facebook_value) setattr(user, f, facebook_value) user_dirty = True #write the raw data in case we missed something if hasattr(profile, 'raw_data'): serialized_fb_data = json.dumps(facebook.facebook_profile_data()) if profile.raw_data != serialized_fb_data: logger.debug('profile raw data changed from %s to %s', profile.raw_data, serialized_fb_data) profile.raw_data = serialized_fb_data profile_dirty = True image_url = facebook_data['image'] if hasattr(profile, 'image') and not profile.image: profile_dirty = _update_image(profile, image_url) #save both models if they changed if user_dirty: user.save() if profile_dirty: profile.save() signals.facebook_post_update.send(sender=get_profile_class(), profile=profile, facebook_data=facebook_data) return user