コード例 #1
0
def check_comments_enabled_for_post_with_id(user, post_id):
    Post = get_post_model()
    post = Post.objects.select_related('community').get(id=post_id)
    if post.community_id is not None:
        if not user.is_staff_of_community_with_name(
                post.community.name) and not post.comments_enabled:
            raise ValidationError(_('Comments are disabled for this post'))
コード例 #2
0
    def handle(self, *args, **options):
        Post = get_post_model()
        PostMedia = get_post_media_model()

        logger.info(Post.objects.filter(media__isnull=False).count())

        posts_to_migrate = Post.objects.filter(Q(media__isnull=False) & Q(media_thumbnail__isnull=True))
        migrated_posts = 0

        for post in posts_to_migrate.iterator():
            with transaction.atomic():
                try:
                    post_first_media = post.get_first_media()
                    if post_first_media.type == PostMedia.MEDIA_TYPE_IMAGE:
                        post.media_width = post_first_media.content_object.width
                        post.media_height = post_first_media.content_object.height
                        post.media_thumbnail = post_first_media.content_object.image.file
                    elif post_first_media.type == PostMedia.MEDIA_TYPE_VIDEO:
                        post.media_width = post_first_media.content_object.width
                        post.media_height = post_first_media.content_object.height
                        post.media_thumbnail = post_first_media.content_object.thumbnail.file

                    post.save()
                except FileNotFoundError as e:
                    print('Ignoring post due to image not found')

            logger.info(post.media_width)
            logger.info(post.media_height)
            logger.info(post.media_thumbnail)

            migrated_posts = migrated_posts + 1

        logger.info('Created media_* for %d posts' % migrated_posts)
コード例 #3
0
def check_can_moderate_moderated_object(user, moderated_object):
    content_object = moderated_object.content_object

    is_global_moderator = user.is_global_moderator()

    if is_global_moderator:
        return

    PostComment = get_post_comment_model()
    Post = get_post_model()

    if isinstance(content_object, Post):
        if content_object.community:
            if not user.is_staff_of_community_with_name(
                    community_name=content_object.community.name):
                raise ValidationError(
                    _('Only community staff can moderate community posts'))
        else:
            raise ValidationError(
                _('Only global moderators can moderate non-community posts'))
    elif isinstance(content_object, PostComment):
        if content_object.post.community:
            if not user.is_staff_of_community_with_name(
                    community_name=content_object.post.community.name):
                raise ValidationError(
                    _('Only community staff can moderate community post comments'
                      ))
        else:
            raise ValidationError(
                _('Only global moderators can moderate non-community post comments'
                  ))
    else:
        raise ValidationError(
            _('Non global moderators can only moderate posts and post comments.'
              ))
コード例 #4
0
def check_can_open_post_with_id(user, post_id):
    Post = get_post_model()
    post = Post.objects.select_related('community').get(id=post_id)
    if post.community_id is None:
        raise ValidationError(_('Only community posts can be opened/closed'))

    if not user.is_staff_of_community_with_name(post.community.name):
        raise ValidationError(
            _('Only administrators/moderators can open this post'))
コード例 #5
0
def check_can_translate_post_with_id(user, post_id):
    Post = get_post_model()
    post = Post.objects.get(id=post_id)
    if post.is_encircled_post():
        raise ValidationError(_('Only public posts can be translated'))
    if post.text is None:
        raise ValidationError(_('Post has no text to be translated'))
    if post.language is None:
        raise ValidationError(
            _('Post has no assigned language to be able to translate'))
    if user.translation_language is None:
        raise ValidationError(
            _('User\'s preferred translation language not set'))
コード例 #6
0
ファイル: assign_language.py プロジェクト: zoist/okuna-api
    def assign_language_posts(self):
        Post = get_post_model()
        posts = Post.objects.filter(text__isnull=False)
        for post in posts:
            try:
                language = get_language_for_text(post.text)
            except LangDetectException as e:
                print('Caught exception while detecting language, skipping')

            if language:
                post.language = language
                post.save()
            else:
                print('Could not detect language for id', post.id)
コード例 #7
0
    def handle(self, *args, **options):
        Post = get_post_model()

        posts_to_migrate = Post.objects.filter(image__isnull=True, media__isnull=False)
        migrated_posts = 0

        for post in posts_to_migrate.iterator():
            with transaction.atomic():
                post_image = post.get_first_media().content_object
                if isinstance(post_image, PostImage):
                    post_image.post = post
                    post_image.save()
                    logger.info('Fixed migrated post with id:' + str(post.pk))
            migrated_posts = migrated_posts + 1

        logger.info('Fixed migrated %d posts' % migrated_posts)
コード例 #8
0
def flush_draft_posts():
    """
    This job should be scheduled to get all pending draft posts for a day and remove them
    """
    Post = get_post_model()

    draft_posts = Post.objects.filter(status=Post.STATUS_DRAFT,
                                      modified__lt=timezone.now() -
                                      timezone.timedelta(days=1)).all()

    flushed_posts = 0

    for draft_post in draft_posts.iterator():
        draft_post.delete()
        flushed_posts = flushed_posts + 1

    return 'Flushed %s posts' % str(flushed_posts)
コード例 #9
0
    def handle(self, *args, **options):
        Post = get_post_model()

        posts_to_process = Post.objects.filter(hashtags__isnull=True,
                                               text__isnull=False,
                                               text__icontains='#').only(
                                                   'id', 'text').all()
        migrated_posts = 0

        for post in _chunked_queryset_iterator(posts_to_process, 100):
            try:
                post._process_post_hashtags()
            except Exception as e:
                logger.info('Error processing with error %s' % str(e))
            logger.info('Processed hashtags for post with id:' + str(post.pk))
            migrated_posts = migrated_posts + 1

        logger.info('Processed %d posts for hashtags' % migrated_posts)
コード例 #10
0
def process_post_media(post_id):
    """
    This job is called to process post media and mark it as published
    """
    Post = get_post_model()
    PostMedia = get_post_media_model()
    post = Post.objects.get(pk=post_id)
    logger.info('Processing media of post with id: %d' % post_id)

    post_media_videos = post.media.filter(type=PostMedia.MEDIA_TYPE_VIDEO)

    for post_media_video in post_media_videos.iterator():
        post_video = post_media_video.content_object
        tasks.convert_video(post_video.file)

    # This updates the status and created attributes
    post._publish()
    logger.info('Processed media of post with id: %d' % post_id)
コード例 #11
0
def check_can_delete_post(user, post):
    Post = get_post_model()

    if not user.has_post(post=post):
        if Post.is_post_with_id_a_community_post(post.pk):
            # If the comment is in a community, check if we're moderators
            if not user.is_moderator_of_community_with_name(
                    post.community.name) and not user.is_administrator_of_community_with_name(post.community.name):
                raise ValidationError(
                    _('Only moderators/administrators can remove community posts.'),
                )
            else:
                # TODO Not the best place to log this but doing the check for community again on delete is wasteful
                post.community.create_remove_post_log(source_user=user,
                                                      target_user=post.creator)
        else:
            raise ValidationError(
                _('You cannot remove a post that does not belong to you')
            )
コード例 #12
0
def check_can_delete_comment_with_id_for_post(user, post_comment_id, post):
    check_can_see_post(user=user, post=post)

    # Check that the comment belongs to the post
    PostComment = get_post_comment_model()
    Post = get_post_model()

    if not PostComment.objects.filter(id=post_comment_id,
                                      post_id=post.pk).exists():
        raise ValidationError(
            _('The comment does not belong to the specified post.'))
    is_comment_creator = user.posts_comments.filter(
        id=post_comment_id).exists()

    if post.community:
        is_moderator = user.is_moderator_of_community_with_name(
            post.community.name)
        is_administrator = user.is_administrator_of_community_with_name(
            post.community.name)
        if not is_administrator and not is_moderator:
            if post.is_closed:
                raise ValidationError(
                    _('Only moderators/administrators can remove closed community posts.'
                      ), )
            elif not is_comment_creator:
                raise ValidationError(
                    _('You cannot remove a comment that does not belong to you'
                      ))
        else:
            # is admin or mod
            post_comment = PostComment.objects.select_related('commenter').get(
                pk=post_comment_id)
            if post_comment.parent_comment is not None:
                post.community.create_remove_post_comment_reply_log(
                    source_user=user, target_user=post_comment.commenter)
            else:
                post.community.create_remove_post_comment_log(
                    source_user=user, target_user=post_comment.commenter)
    elif not post.creator_id == user.pk and not is_comment_creator:
        # not a community post
        raise ValidationError(
            _('You cannot remove a comment that does not belong to you'))
コード例 #13
0
    def handle(self, *args, **options):
        Post = get_post_model()
        PostMedia = get_post_media_model()

        posts_to_migrate = Post.objects.filter(image__isnull=False,
                                               media__isnull=True)
        migrated_posts = 0

        for post in posts_to_migrate.iterator():
            with transaction.atomic():
                post_image = post.image
                PostMedia.create_post_media(type=PostMedia.MEDIA_TYPE_IMAGE,
                                            content_object=post_image,
                                            post_id=post.pk,
                                            order=0)
                post_image.save()
            logger.info('Migrated post with id:' + str(post.pk))
            migrated_posts = migrated_posts + 1

        logger.info('Migrated %d posts' % migrated_posts)
コード例 #14
0
    def unverify_with_actor_with_id(self, actor_id):
        current_verified = self.verified
        self.verified = False
        ModeratedObjectVerifiedChangedLog.create_moderated_object_verified_changed_log(
            changed_from=current_verified, changed_to=self.verified, moderated_object_id=self.pk, actor_id=actor_id)
        self.user_penalties.all().delete()
        content_object = self.content_object

        Post = get_post_model()
        PostComment = get_post_comment_model()
        Community = get_community_model()
        moderation_severity = self.category.severity

        if (isinstance(content_object, Post) or isinstance(content_object, PostComment) or isinstance(
                content_object,
                Community)) or (
                isinstance(content_object, User) and moderation_severity == ModerationCategory.SEVERITY_CRITICAL):
            content_object.unsoft_delete()
        self.save()
        content_object.save()
コード例 #15
0
    def approve_with_actor_with_id(self, actor_id):
        Post = get_post_model()
        PostComment = get_post_comment_model()
        Community = get_community_model()
        User = get_user_model()

        content_object = self.content_object
        moderation_severity = self.category.severity
        current_status = self.status
        self.status = ModeratedObject.STATUS_APPROVED
        ModeratedObjectStatusChangedLog.create_moderated_object_status_changed_log(
            changed_from=current_status, changed_to=self.status, moderated_object_id=self.pk, actor_id=actor_id)

        if isinstance(content_object, Post) or \
                isinstance(content_object, PostComment) or \
                isinstance(content_object, Community):
            content_object.delete_notifications()

        if isinstance(content_object, User) and moderation_severity == ModerationCategory.SEVERITY_CRITICAL:
            content_object.delete_outgoing_notifications()

        self.save()
コード例 #16
0
    def handle(self, *args, **options):
        Post = get_post_model()

        text_query = Q(
            text__isnull=False,
            text__icontains='http',
        )

        links_query = Q(links__isnull=True) | Q(links__has_preview=False)

        posts_to_process = Post.objects.filter(text_query & links_query).only(
            'id', 'text').all()
        migrated_posts = 0

        for post in _chunked_queryset_iterator(posts_to_process, 100):
            try:
                post._process_post_links()
            except Exception as e:
                logger.info('Error processing with error %s' % str(e))
            logger.info('Processed links for post with id:' + str(post.pk))
            migrated_posts = migrated_posts + 1

        logger.info('Processed %d posts for links' % migrated_posts)
コード例 #17
0
    def to_representation(self, post):
        request = self.context.get('request')
        request_user = request.user

        reaction_emoji_count = []

        if request_user.is_anonymous:
            if post.public_reactions:
                Post = get_post_model()
                reaction_emoji_count = Post.get_emoji_counts_for_post_with_id(
                    post.pk)
        else:
            reaction_emoji_count = request_user.get_emoji_counts_for_post_with_id(
                post.pk)

        post_reactions_serializer = self.emoji_count_serializer(
            reaction_emoji_count,
            many=True,
            context={
                "request": request,
                'post': post
            })

        return post_reactions_serializer.data
コード例 #18
0
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()
コード例 #19
0
ファイル: queries.py プロジェクト: zoist/okuna-api
def make_only_published_posts_query():
    # Only retrieve published posts
    Post = get_post_model()
    return Q(status=Post.STATUS_PUBLISHED)
コード例 #20
0
    def verify_with_actor_with_id(self, actor_id):
        current_verified = self.verified
        self.verified = True
        ModeratedObjectVerifiedChangedLog.create_moderated_object_verified_changed_log(
            changed_from=current_verified, changed_to=self.verified, moderated_object_id=self.pk, actor_id=actor_id)

        Post = get_post_model()
        Hashtag = get_hashtag_model()
        PostComment = get_post_comment_model()
        Community = get_community_model()
        User = get_user_model()
        ModerationPenalty = get_moderation_penalty_model()

        content_object = self.content_object
        moderation_severity = self.category.severity
        penalty_targets = None

        if self.is_approved():
            if isinstance(content_object, User):
                penalty_targets = [content_object]
            elif isinstance(content_object, Post):
                penalty_targets = [content_object.creator]
            elif isinstance(content_object, PostComment):
                penalty_targets = [content_object.commenter]
            elif isinstance(content_object, Community):
                penalty_targets = content_object.get_staff_members()
            elif isinstance(content_object, ModeratedObject):
                penalty_targets = content_object.get_reporters()
            elif isinstance(content_object, Hashtag):
                penalty_targets = []

            for penalty_target in penalty_targets:
                duration_of_penalty = None
                penalties_count = penalty_target.count_moderation_penalties_for_moderation_severity(
                    moderation_severity=moderation_severity) + 1

                if moderation_severity == ModerationCategory.SEVERITY_CRITICAL:
                    duration_of_penalty = timezone.timedelta(weeks=5000)
                elif moderation_severity == ModerationCategory.SEVERITY_HIGH:
                    duration_of_penalty = timezone.timedelta(days=penalties_count ** 4)
                elif moderation_severity == ModerationCategory.SEVERITY_MEDIUM:
                    duration_of_penalty = timezone.timedelta(hours=penalties_count ** 3)
                elif moderation_severity == ModerationCategory.SEVERITY_LOW:
                    duration_of_penalty = timezone.timedelta(minutes=penalties_count ** 2)

                moderation_expiration = timezone.now() + duration_of_penalty

                ModerationPenalty.create_suspension_moderation_penalty(moderated_object=self,
                                                                       user_id=penalty_target.pk,
                                                                       expiration=moderation_expiration)

            if (isinstance(content_object, Post) or isinstance(content_object, PostComment) or isinstance(
                    content_object,
                    Community)) or (
                    isinstance(content_object, User) and moderation_severity == ModerationCategory.SEVERITY_CRITICAL):
                content_object.soft_delete()

                if moderation_severity == ModerationCategory.SEVERITY_CRITICAL and isinstance(content_object, Post):
                    # We have hashes
                    content_object.delete_media()

        content_object.save()
        self.save()
コード例 #21
0
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()
コード例 #22
0
    def __init__(self):
        PostReaction = get_post_reaction_model()
        PostComment = get_post_comment_model()
        User = get_user_model()
        Emoji = get_emoji_model()
        Post = get_post_model()
        CommunityInvite = get_community_invite_model()
        Community = get_community_model()

        class NotificationUserSerializer(serializers.ModelSerializer):
            class Meta:
                model = User
                fields = (
                    'id',
                    'username',
                )

        class NotificationEmojiSerializer(serializers.ModelSerializer):
            class Meta:
                model = Emoji
                fields = (
                    'id',
                    'keyword',
                )

        class NotificationPostSerializer(serializers.ModelSerializer):
            class Meta:
                model = Post
                fields = (
                    'id',
                    'uuid',
                )

        class NotificationPostReactionSerializer(serializers.ModelSerializer):
            reactor = NotificationUserSerializer()
            emoji = NotificationEmojiSerializer()
            post = NotificationPostSerializer()

            class Meta:
                model = PostReaction
                fields = ('id', 'reactor', 'emoji', 'post')

        self.NotificationPostReactionSerializer = NotificationPostReactionSerializer

        class NotificationCommunitySerializer(serializers.ModelSerializer):
            class Meta:
                model = Community
                fields = ('id', 'name', 'title')

        class NotificationCommunityInviteSerializer(serializers.ModelSerializer
                                                    ):
            creator = NotificationUserSerializer()
            invited_user = NotificationUserSerializer()
            community = NotificationCommunitySerializer()

            class Meta:
                model = CommunityInvite
                fields = ('id', 'creator', 'invited_user', 'community')

        self.NotificationCommunityInviteSerializer = NotificationCommunityInviteSerializer

        class NotificationPostCommentSerializer(serializers.ModelSerializer):
            commenter = NotificationUserSerializer()
            post = NotificationPostSerializer()

            class Meta:
                model = PostComment
                fields = ('id', 'commenter', 'post')

        self.NotificationPostCommentSerializer = NotificationPostCommentSerializer

        class NotificationPostCommentReplySerializer(
                serializers.ModelSerializer):
            commenter = NotificationUserSerializer()
            post = NotificationPostSerializer()

            class Meta:
                model = PostComment
                fields = ('id', 'commenter', 'post')

        self.NotificationPostCommentReplySerializer = NotificationPostCommentReplySerializer

        class FollowNotificationSerializer(serializers.Serializer):
            following_user = NotificationUserSerializer()

        self.FollowNotificationSerializer = FollowNotificationSerializer

        class ConnectionRequestNotificationSerializer(serializers.Serializer):
            connection_requester = NotificationUserSerializer()

        self.ConnectionRequestNotificationSerializer = ConnectionRequestNotificationSerializer
コード例 #23
0
ファイル: views.py プロジェクト: sergray/openbook-api
 def get(self, request):
     Post = get_post_model()
     posts = Post.get_trending_posts()[:30]
     posts_serializer = AuthenticatedUserPostSerializer(
         posts, many=True, context={"request": request})
     return Response(posts_serializer.data, status=status.HTTP_200_OK)
コード例 #24
0
ファイル: validators.py プロジェクト: zoist/okuna-api
def post_id_exists(post_id):
    Post = get_post_model()
    if not Post.objects.filter(id=post_id).exists():
        raise ValidationError(_('The post does not exist.'), )
コード例 #25
0
def get_post_id_for_post_uuid(post_uuid):
    Post = get_post_model()
    return Post.get_post_id_for_post_with_uuid(post_uuid=post_uuid)
コード例 #26
0
ファイル: validators.py プロジェクト: zoist/okuna-api
def post_uuid_exists(post_uuid):
    Post = get_post_model()

    if not Post.objects.filter(uuid=post_uuid).exists():
        raise NotFound(_('The post does not exist.'), )
コード例 #27
0
def get_post_id_for_post_uuid(post_uuid):
    Post = get_post_model()
    post = Post.objects.values('id').get(uuid=post_uuid)
    return post['id']
コード例 #28
0
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)
コード例 #29
0
ファイル: checkers.py プロジェクト: zoist/okuna-api
def check_is_not_processing(post):
    Post = get_post_model()
    if post.status == Post.STATUS_PROCESSING:
        raise ValidationError(_('The post is being processed'))
コード例 #30
0
ファイル: checkers.py プロジェクト: zoist/okuna-api
def check_is_not_published(post):
    Post = get_post_model()
    if post.status == Post.STATUS_PUBLISHED:
        raise ValidationError(_('The post is already published'))