def usernames(request): """An API to provide auto-complete data for user names.""" term = request.GET.get("term", "") query = request.GET.get("query", "") pre = term or query if not pre: return [] if not request.user.is_authenticated: return [] profile_ids = list( Profile.objects.filter(Q(name__istartswith=pre)).values_list( "user_id", flat=True)[:10]) users = (User.objects.filter( Q(username__istartswith=pre) | Q(id__in=profile_ids)).filter( is_active=True).select_related("profile"))[:10] autocomplete_list = [] exact_match_in_list = False for user in users: if user.username.lower() == pre.lower(): exact_match_in_list = True autocomplete_list.append({ "username": user.username, "display_name": display_name_or_none(user), "avatar": profile_avatar(user, 24), }) if not exact_match_in_list: # The front-end dropdown which uses this API requires the exact match to be in the list # if it exists, so that user can be selected. Our code above won't necessarily always # return an exact match, even if it exists, so if it's missing attempt to fetch it and # prepend it to the list try: exact_match = (User.objects.filter(username__iexact=pre).filter( is_active=True).select_related("profile").get()) autocomplete_list = [ { "username": exact_match.username, "display_name": display_name_or_none(exact_match), "avatar": profile_avatar(exact_match, 24), } ] + autocomplete_list except User.DoesNotExist: pass return autocomplete_list
def test_profile_avatar(self): self.u.profile.avatar = 'images/foo.png' self.u.profile.save() email_hash = hashlib.md5(self.u.email.lower()).hexdigest() gravatar_url = 'https://secure.gravatar.com/avatar/%s?s=48' % ( email_hash) assert profile_avatar(self.u).startswith(gravatar_url)
def test_creator_is_object(self): serializer = api.QuestionSerializer(instance=self.question) eq_(serializer.data['creator'], { 'username': self.question.creator.username, 'display_name': Profile.objects.get(user=self.question.creator).display_name, 'avatar': profile_avatar(self.question.creator), })
def usernames(request): """An API to provide auto-complete data for user names.""" term = request.GET.get('term', '') query = request.GET.get('query', '') pre = term or query if not pre: return [] if not request.user.is_authenticated(): return [] with statsd.timer('users.api.usernames.search'): profiles = ( Profile.objects.filter(Q(name__istartswith=pre)) .values_list('user_id', flat=True)) users = ( User.objects.filter( Q(username__istartswith=pre) | Q(id__in=profiles)) .extra(select={'length': 'Length(username)'}) .order_by('length').select_related('profile')) if not waffle.switch_is_active('users-dont-limit-by-login'): last_login = datetime.now() - timedelta(weeks=12) users = users.filter(last_login__gte=last_login) return [{'username': u.username, 'display_name': display_name_or_none(u), 'avatar': profile_avatar(u, 24)} for u in users[:10]]
def usernames(request): """An API to provide auto-complete data for user names.""" term = request.GET.get('term', '') query = request.GET.get('query', '') pre = term or query if not pre: return [] if not request.user.is_authenticated(): return [] with statsd.timer('users.api.usernames.search'): profiles = (Profile.objects.filter( Q(name__istartswith=pre)).values_list('user_id', flat=True)) users = (User.objects.filter( Q(username__istartswith=pre) | Q(id__in=profiles)).extra(select={ 'length': 'Length(username)' }).order_by('length').select_related('profile')) if not waffle.switch_is_active('users-dont-limit-by-login'): last_login = datetime.now() - timedelta(weeks=12) users = users.filter(last_login__gte=last_login) return [{ 'username': u.username, 'display_name': display_name_or_none(u), 'avatar': profile_avatar(u, 24) } for u in users[:10]]
def test_correct_fields(self): follower = UserFactory() followed = UserFactory() q = QuestionFactory(creator=followed) # The above might make follows, which this test isn't about. Clear them out. Follow.objects.all().delete() follow(follower, followed) # Make a new action for the above. This should trigger notifications action.send(followed, verb='asked', action_object=q) act = Action.objects.order_by('-id')[0] notification = Notification.objects.get(action=act) serializer = api.NotificationSerializer(instance=notification) eq_(serializer.data['is_read'], False) eq_(serializer.data['actor'], { 'type': 'user', 'username': followed.username, 'display_name': followed.profile.name, 'avatar': profile_avatar(followed), }) eq_(serializer.data['verb'], 'asked') eq_(serializer.data['action_object']['type'], 'question') eq_(serializer.data['action_object']['id'], q.id) eq_(serializer.data['target'], None) # Check that the serialized data is in the correct format. If it is # not, this will throw an exception. datetime.strptime(serializer.data['timestamp'], '%Y-%m-%dT%H:%M:%SZ')
def usernames(request): """An API to provide auto-complete data for user names.""" term = request.GET.get("term", "") query = request.GET.get("query", "") pre = term or query if not pre: return [] if not request.user.is_authenticated: return [] profiles = Profile.objects.filter(Q(name__istartswith=pre)).values_list( "user_id", flat=True) users = (User.objects.filter( Q(username__istartswith=pre) | Q(id__in=profiles)).extra(select={ "length": "Length(username)" }).order_by("length").select_related("profile")) if not waffle.switch_is_active("users-dont-limit-by-login"): last_login = datetime.now() - timedelta(weeks=12) users = users.filter(last_login__gte=last_login) return [{ "username": u.username, "display_name": display_name_or_none(u), "avatar": profile_avatar(u, 24), } for u in users[:10]]
def _get_creator_counts(query, count, page): total = query.count() results = [] now = datetime.now() for user in query[((page - 1) * count):(page * count)]: last_contribution_date = user.profile.last_contribution_date days_since_last_activity = None if last_contribution_date: days_since_last_activity = now - last_contribution_date data = { 'count': user.query_count, 'term': user.id, 'user': { 'id': user.id, 'username': user.username, 'display_name': user.profile.display_name, 'avatar': profile_avatar(user, size=120), 'twitter_usernames': user.profile.twitter_usernames, 'last_contribution_date': last_contribution_date, 'days_since_last_activity': days_since_last_activity, } } results.append(data) return (results, total)
def top_contributors_l10n(start=None, end=None, locale=None, product=None, count=10, page=1, use_cache=True): """Get the top l10n contributors for the KB.""" if use_cache: cache_key = "{}_{}_{}_{}_{}_{}".format(start, end, locale, product, count, page) cache_key = hashlib.sha1(cache_key.encode("utf-8")).hexdigest() cache_key = "top_contributors_l10n_{}".format(cache_key) cached = cache.get(cache_key, None) if cached: return cached # Get the user ids and contribution count of the top contributors. revisions = Revision.objects.all() if locale is None: # If there is no locale specified, exclude en-US only. The rest are # l10n. revisions = revisions.exclude( document__locale=settings.WIKI_DEFAULT_LANGUAGE) if start is None: # By default we go back 90 days. start = date.today() - timedelta(days=90) revisions = revisions.filter(created__gte=start) if end: # If no end is specified, we don't need to filter by it. revisions = revisions.filter(created__lt=end) if locale: revisions = revisions.filter(document__locale=locale) if product: if isinstance(product, Product): product = product.slug revisions = revisions.filter( Q(document__products__slug=product) | Q(document__parent__products__slug=product)) users = (User.objects.filter( created_revisions__in=revisions, is_active=True).annotate( query_count=Count("created_revisions")).order_by( "-query_count").select_related("profile")) total = users.count() results = [{ "term": user.pk, "count": user.query_count, "user": { "id": user.pk, "username": user.username, "display_name": user.profile.display_name, "avatar": profile_avatar(user), }, } for user in users[(page - 1) * count:page * count]] if use_cache: cache.set(cache_key, (results, total), settings.CACHE_MEDIUM_TIMEOUT) return results, total
def test_correct_fields(self): follower = UserFactory() followed = UserFactory() q = QuestionFactory(creator=followed) # The above might make follows, which this test isn't about. Clear them out. Follow.objects.all().delete() follow(follower, followed) # Make a new action for the above. This should trigger notifications action.send(followed, verb="asked", action_object=q) act = Action.objects.order_by("-id")[0] notification = Notification.objects.get(action=act) serializer = api.NotificationSerializer(instance=notification) eq_(serializer.data["is_read"], False) eq_( serializer.data["actor"], { "type": "user", "username": followed.username, "display_name": followed.profile.name, "avatar": profile_avatar(followed), }, ) eq_(serializer.data["verb"], "asked") eq_(serializer.data["action_object"]["type"], "question") eq_(serializer.data["action_object"]["id"], q.id) eq_(serializer.data["target"], None) # Check that the serialized data is in the correct format. If it is # not, this will throw an exception. datetime.strptime(serializer.data["timestamp"], "%Y-%m-%dT%H:%M:%SZ")
def test_correct_fields(self): follower = UserFactory() followed = UserFactory() q = QuestionFactory(creator=followed) # The above might make follows, which this test isn't about. Clear them out. Follow.objects.all().delete() follow(follower, followed) # Make a new action for the above. This should trigger notifications action.send(followed, verb='asked', action_object=q) act = Action.objects.order_by('-id')[0] notification = Notification.objects.get(action=act) serializer = api.NotificationSerializer(instance=notification) eq_(serializer.data['is_read'], False) eq_( serializer.data['actor'], { 'type': 'user', 'username': followed.username, 'display_name': followed.profile.name, 'avatar': profile_avatar(followed), }) eq_(serializer.data['verb'], 'asked') eq_(serializer.data['action_object']['type'], 'question') eq_(serializer.data['action_object']['id'], q.id) eq_(serializer.data['target'], None) # Check that the serialized data is in the correct format. If it is # not, this will throw an exception. datetime.strptime(serializer.data['timestamp'], '%Y-%m-%dT%H:%M:%SZ')
def _names(self, *users): return sorted( { 'username': u.username, 'display_name': Profile.objects.get(user=u).name, 'avatar': profile_avatar(u), } for u in users)
def _names(self, *users): return sorted(( { 'username': u.username, 'display_name': Profile.objects.get(user=u).name, 'avatar': profile_avatar(u), } for u in users), key=lambda d: d['username'])
def _names(self, *users): return sorted( ({ "username": u.username, "display_name": Profile.objects.get(user=u).name, "avatar": profile_avatar(u), } for u in users), key=lambda d: d["username"], )
def test_creator_is_object(self): serializer = api.QuestionSerializer(instance=self.question) eq_( serializer.data["creator"], { "username": self.question.creator.username, "display_name": Profile.objects.get(user=self.question.creator).display_name, "avatar": profile_avatar(self.question.creator), }, )
def extract_document(cls, obj_id, obj=None): """Extracts interesting thing from a Thread and its Posts""" if obj is None: model = cls.get_model() obj = model.objects.select_related("user").get(pk=obj_id) if not obj.user.is_active: raise UnindexMeBro() d = {} d["id"] = obj.pk d["model"] = cls.get_mapping_type_name() d["url"] = obj.get_absolute_url() d["indexed_on"] = int(time.time()) d["username"] = obj.user.username d["display_name"] = obj.display_name d["twitter_usernames"] = obj.twitter_usernames d["last_contribution_date"] = obj.last_contribution_date d["iusername"] = obj.user.username.lower() d["idisplay_name"] = obj.display_name.lower() d["itwitter_usernames"] = [u.lower() for u in obj.twitter_usernames] from kitsune.users.templatetags.jinja_helpers import profile_avatar d["avatar"] = profile_avatar(obj.user, size=120) d["suggest"] = { "input": [d["iusername"], d["idisplay_name"]], "output": _("{displayname} ({username})").format( displayname=d["display_name"], username=d["username"]), "payload": { "user_id": d["id"] }, } return d
def extract_document(cls, obj_id, obj=None): """Extracts interesting thing from a Thread and its Posts""" if obj is None: model = cls.get_model() obj = model.objects.select_related('user').get(pk=obj_id) if not obj.user.is_active: raise UnindexMeBro() d = {} d['id'] = obj.pk d['model'] = cls.get_mapping_type_name() d['url'] = obj.get_absolute_url() d['indexed_on'] = int(time.time()) d['username'] = obj.user.username d['display_name'] = obj.display_name d['twitter_usernames'] = obj.twitter_usernames d['last_contribution_date'] = obj.last_contribution_date d['iusername'] = obj.user.username.lower() d['idisplay_name'] = obj.display_name.lower() d['itwitter_usernames'] = [u.lower() for u in obj.twitter_usernames] from kitsune.users.templatetags.jinja_helpers import profile_avatar d['avatar'] = profile_avatar(obj.user, size=120) d['suggest'] = { 'input': [ d['iusername'], d['idisplay_name'] ], 'output': _(u'{displayname} ({username})').format( displayname=d['display_name'], username=d['username']), 'payload': {'user_id': d['id']}, } return d
def extract_document(cls, obj_id, obj=None): """Extracts interesting thing from a Thread and its Posts""" if obj is None: model = cls.get_model() obj = model.objects.select_related('user').get(pk=obj_id) if not obj.user.is_active: raise UnindexMeBro() d = {} d['id'] = obj.pk d['model'] = cls.get_mapping_type_name() d['url'] = obj.get_absolute_url() d['indexed_on'] = int(time.time()) d['username'] = obj.user.username d['display_name'] = obj.display_name d['twitter_usernames'] = obj.twitter_usernames d['last_contribution_date'] = obj.last_contribution_date d['iusername'] = obj.user.username.lower() d['idisplay_name'] = obj.display_name.lower() d['itwitter_usernames'] = [u.lower() for u in obj.twitter_usernames] from kitsune.users.templatetags.jinja_helpers import profile_avatar d['avatar'] = profile_avatar(obj.user, size=120) d['suggest'] = { 'input': [d['iusername'], d['idisplay_name']], 'output': _(u'{displayname} ({username})').format( displayname=d['display_name'], username=d['username']), 'payload': { 'user_id': d['id'] }, } return d
def test_profile_avatar_anonymous(self): email_hash = '00000000000000000000000000000000' gravatar_url = 'https://secure.gravatar.com/avatar/%s?s=48' % ( email_hash) assert profile_avatar(AnonymousUser()).startswith(gravatar_url)
def test_profile_avatar_default(self): email_hash = hashlib.md5(self.u.email.lower()).hexdigest() gravatar_url = 'https://secure.gravatar.com/avatar/%s?s=48' % ( email_hash) assert profile_avatar(self.u).startswith(gravatar_url)
def test_profile_avatar_unicode(self): self.u.email = u'rá[email protected]' self.u.save() gravatar_url = 'https://secure.gravatar.com/' assert profile_avatar(self.u).startswith(gravatar_url)
def get_avatar_url(self, profile): request = self.context.get('request') size = request.REQUEST.get('avatar_size', 48) if request else 48 return profile_avatar(profile.user, size=size)
def get_avatar_url(self, profile): request = self.context.get("request") size = request.GET.get("avatar_size", 200) if request else 200 return profile_avatar(profile.user, size=size)