def count_replies_with_user(self, user): # Count replies excluding users blocked by authenticated user count_query = ~Q( Q(commenter__blocked_by_users__blocker_id=user.pk) | Q(commenter__user_blocks__blocked_user_id=user.pk)) if self.post.community: if not user.is_staff_of_community_with_name( community_name=self.post.community.name): # Dont retrieve comments except from staff members blocked_users_query_staff_members = Q( commenter__communities_memberships__community_id=self.post. community.pk) blocked_users_query_staff_members.add( Q(commenter__communities_memberships__is_administrator=True ) | Q(commenter__communities_memberships__is_moderator=True), Q.AND) count_query.add(~blocked_users_query_staff_members, Q.AND) # Don't count items that have been reported and approved by community moderators ModeratedObject = get_moderated_object_model() count_query.add( ~Q(moderated_object__status=ModeratedObject.STATUS_APPROVED), Q.AND) # Dont count soft deleted items count_query.add(Q(is_deleted=False), Q.AND) # Dont count items we have reported count_query.add(~Q(moderated_object__reports__reporter_id=user.pk), Q.AND) return self.replies.filter(count_query).count()
def count_replies_with_user(self, user): count_query = Q() if self.post.community_id: # Don't count items that have been reported and approved by community moderators ModeratedObject = get_moderated_object_model() count_query.add(~Q(moderated_object__status=ModeratedObject.STATUS_APPROVED), Q.AND) # Dont count soft deleted items count_query.add(Q(is_deleted=False), Q.AND) # Dont count items we have reported count_query.add(~Q(moderated_object__reports__reporter_id=user.pk), Q.AND) return self.replies.filter(count_query).count()
def count_comments_with_user(self, user): # Only count top level comments count_query = Q(parent_comment__isnull=True) if self.community: # Don't count items that have been reported and approved by community moderators ModeratedObject = get_moderated_object_model() count_query.add(~Q(moderated_object__status=ModeratedObject.STATUS_APPROVED), Q.AND) # Dont count soft deleted items count_query.add(Q(is_deleted=False), Q.AND) # Dont count items we have reported count_query.add(~Q(moderated_object__reports__reporter_id=user.pk), Q.AND) return self.comments.filter(count_query).count()
def count_pending_moderated_objects(self): ModeratedObject = get_moderated_object_model() return self.moderated_objects.filter(status=ModeratedObject.STATUS_PENDING).count()
def curate_top_posts(): """ Curates the top posts. This job should be scheduled to be run every n hours. """ Post = get_post_model() Community = get_community_model() PostComment = get_post_comment_model() ModeratedObject = get_moderated_object_model() TopPost = get_top_post_model() logger.info('Processing top posts at %s...' % timezone.now()) top_posts_community_query = Q(top_post__isnull=True) top_posts_community_query.add( Q(community__isnull=False, community__type=Community.COMMUNITY_TYPE_PUBLIC), Q.AND) top_posts_community_query.add( Q(is_closed=False, is_deleted=False, status=Post.STATUS_PUBLISHED), Q.AND) top_posts_community_query.add( ~Q(moderated_object__status=ModeratedObject.STATUS_APPROVED), Q.AND) top_posts_criteria_query = Q(total_comments_count__gte=settings.MIN_UNIQUE_TOP_POST_COMMENTS_COUNT) | \ Q(reactions_count__gte=settings.MIN_UNIQUE_TOP_POST_REACTIONS_COUNT) posts_select_related = 'community' posts_prefetch_related = ('comments__commenter', 'reactions__reactor') posts_only = ('id', 'status', 'is_deleted', 'is_closed', 'community__type') posts = Post.objects. \ select_related(posts_select_related). \ prefetch_related(*posts_prefetch_related). \ only(*posts_only). \ filter(top_posts_community_query). \ annotate(total_comments_count=Count('comments__commenter_id'), reactions_count=Count('reactions__reactor_id')). \ filter(top_posts_criteria_query) top_posts_objects = [] total_checked_posts = 0 total_curated_posts = 0 for post in _chunked_queryset_iterator(posts, 1000): total_checked_posts = total_checked_posts + 1 if not post.reactions_count >= settings.MIN_UNIQUE_TOP_POST_REACTIONS_COUNT: unique_comments_count = PostComment.objects.filter(post=post). \ values('commenter_id'). \ annotate(user_comments_count=Count('commenter_id')).count() if unique_comments_count >= settings.MIN_UNIQUE_TOP_POST_COMMENTS_COUNT: top_post = _add_post_to_top_post(post=post) if top_post is not None: top_posts_objects.append(top_post) else: top_post = _add_post_to_top_post(post=post) if top_post is not None: top_posts_objects.append(top_post) if len(top_posts_objects) > 1000: TopPost.objects.bulk_create(top_posts_objects) total_curated_posts += len(top_posts_objects) top_posts_objects = [] if len(top_posts_objects) > 0: total_curated_posts += len(top_posts_objects) TopPost.objects.bulk_create(top_posts_objects) return 'Checked: %d. Curated: %d' % (total_checked_posts, total_curated_posts)
def clean_top_posts(): """ Cleans up top posts, that no longer meet the criteria. """ Post = get_post_model() Community = get_community_model() TopPost = get_top_post_model() PostComment = get_post_comment_model() ModeratedObject = get_moderated_object_model() # if any of these is true, we will remove the top post top_posts_community_query = Q( post__community__type=Community.COMMUNITY_TYPE_PRIVATE) top_posts_community_query.add(Q(post__is_closed=True), Q.OR) top_posts_community_query.add(Q(post__is_deleted=True), Q.OR) top_posts_community_query.add(Q(post__status=Post.STATUS_DRAFT), Q.OR) top_posts_community_query.add(Q(post__status=Post.STATUS_PROCESSING), Q.OR) top_posts_community_query.add( Q(post__moderated_object__status=ModeratedObject.STATUS_APPROVED), Q.OR) # counts less than minimum top_posts_criteria_query = Q(total_comments_count__lt=settings.MIN_UNIQUE_TOP_POST_COMMENTS_COUNT) & \ Q(reactions_count__lt=settings.MIN_UNIQUE_TOP_POST_REACTIONS_COUNT) posts_select_related = 'post__community' posts_prefetch_related = ('post__comments__commenter', 'post__reactions__reactor') posts_only = ('post__id', 'post__status', 'post__is_deleted', 'post__is_closed', 'post__community__type') direct_removable_top_posts = TopPost.objects.select_related(posts_select_related). \ prefetch_related(*posts_prefetch_related). \ only(*posts_only). \ filter(top_posts_community_query). \ annotate(total_comments_count=Count('post__comments__commenter_id'), reactions_count=Count('post__reactions__reactor_id')). \ filter(top_posts_criteria_query) # bulk delete all that definitely dont meet the criteria anymore direct_removable_top_posts.delete() # Now we need to only check the ones where the unique comments count might have dropped, # while all other criteria is fine top_posts_community_query = Q( post__community__isnull=False, post__community__type=Community.COMMUNITY_TYPE_PUBLIC) top_posts_community_query.add( Q(post__is_closed=False, post__is_deleted=False, post__status=Post.STATUS_PUBLISHED), Q.AND) top_posts_community_query.add( ~Q(post__moderated_object__status=ModeratedObject.STATUS_APPROVED), Q.AND) top_posts_criteria_query = Q(total_comments_count__gte=settings.MIN_UNIQUE_TOP_POST_COMMENTS_COUNT) | \ Q(reactions_count__gte=settings.MIN_UNIQUE_TOP_POST_REACTIONS_COUNT) top_posts = TopPost.objects.select_related(posts_select_related). \ prefetch_related(*posts_prefetch_related). \ only(*posts_only). \ filter(top_posts_community_query). \ annotate(total_comments_count=Count('post__comments__commenter_id'), reactions_count=Count('post__reactions__reactor_id')). \ filter(top_posts_criteria_query) delete_ids = [] for top_post in _chunked_queryset_iterator(top_posts, 1000): if not top_post.reactions_count >= settings.MIN_UNIQUE_TOP_POST_REACTIONS_COUNT: unique_comments_count = PostComment.objects.filter(post=top_post.post). \ values('commenter_id'). \ annotate(user_comments_count=Count('commenter_id')).count() if unique_comments_count < settings.MIN_UNIQUE_TOP_POST_COMMENTS_COUNT: delete_ids.append(top_post.pk) # bulk delete ids TopPost.objects.filter(id__in=delete_ids).delete()
def get_posts_for_user_collection(target_user, source_user, posts_only=None, posts_prefetch_related=None, max_id=None, min_id=None, include_community_posts=False): Post = get_post_model() posts_collection_manager = Post.objects if posts_prefetch_related: posts_collection_manager = posts_collection_manager.prefetch_related( *posts_prefetch_related) if posts_only: posts_collection_manager = posts_collection_manager.only(*posts_only) id_boundary_query = None if max_id: id_boundary_query = make_only_posts_with_max_id(max_id=max_id) elif min_id: id_boundary_query = make_only_posts_with_min_id(min_id=min_id) query = Q( # Created by the target user creator__username=target_user.username, # Not closed is_closed=False, # Not deleted is_deleted=False, # Published status=Post.STATUS_PUBLISHED, ) posts_query = make_circles_posts_query_for_user(user=source_user) if include_community_posts: posts_query.add(make_community_posts_query_for_user(user=source_user), Q.OR) query.add(posts_query, Q.AND) if id_boundary_query: query.add(id_boundary_query, Q.AND) ModeratedObject = get_moderated_object_model() posts_visibility_exclude_query = Q( # Reported posts Q(moderated_object__reports__reporter_id=source_user.pk) | # Approved reported posts Q(moderated_object__status=ModeratedObject.STATUS_APPROVED) | # Posts of users we blocked or that have blocked us Q(creator__blocked_by_users__blocker_id=source_user.pk) | Q(creator__user_blocks__blocked_user_id=source_user.pk) | # Posts of communities banned from Q(community__banned_users__id=source_user.pk)) return posts_collection_manager.filter(query).exclude( posts_visibility_exclude_query).distinct()
def make_exclude_reported_and_approved_hashtags_query(): ModeratedObject = get_moderated_object_model() return ~Q(moderated_object__status=ModeratedObject.STATUS_APPROVED)