def create(self, request, *args, **kwargs):
        # Is deprecated?
        user = request.user
        if not user.is_anonymous:
            request.data['user'] = user.id

        created_location = request.data.get('created_location')
        if created_location is not None:
            created_location = created_location.upper()
            request.data['created_location'] = created_location
        else:
            return Response('Missing required field `created_location`',
                            status=status.HTTP_400_BAD_REQUEST)

        interaction = request.data.get('interaction', None)
        if interaction is not None:
            interaction = interaction.upper()
            request.data['interaction'] = interaction

        paper_id = request.data['paper']
        res = super().create(request, *args, **kwargs)
        paper_event_id = res.data['id']
        if created_location == PaperEvent.PAPER and PaperEvent.VIEW:
            create_contribution.apply_async((Contribution.SUPPORTER, {
                'app_label': 'analytics',
                'model': 'paperevent'
            }, user.id, paper_id, paper_event_id),
                                            priority=2,
                                            countdown=10)
Exemple #2
0
    def _create_contribution(self, decision):
        use_async = True
        if TESTING:
            use_async = False

        app_label = decision._meta.app_label
        model = decision._meta.model.__name__.lower()
        user_id = decision.peer_review.assigned_user.id
        unified_doc_id = decision.unified_document.id
        obj_id = decision.id

        if use_async:
            create_contribution.apply_async((Contribution.PEER_REVIEWER, {
                'app_label': app_label,
                'model': model
            }, user_id, unified_doc_id, obj_id),
                                            priority=1,
                                            countdown=10)
        else:
            create_contribution(contribution_type=Contribution.PEER_REVIEWER,
                                instance_type={
                                    'app_label': app_label,
                                    'model': model
                                },
                                user_id=user_id,
                                unified_doc_id=unified_doc_id,
                                object_id=obj_id)
    def create(self, request, *args, **kwargs):
        document_type = request.path.split('/')[2]
        document_id = get_document_id_from_path(request)
        document = RELATED_DISCUSSION_MODELS[document_type].objects.get(
            id=document_id)
        unified_document = document.unified_document
        unified_doc_id = unified_document.id

        if request.query_params.get('created_location') == 'progress':
            request.data['created_location'] = (
                BaseComment.CREATED_LOCATION_PROGRESS)

        response = super().create(request, *args, **kwargs)
        hubs = list(unified_document.hubs.all().values_list('id', flat=True))
        self.sift_track_create_content_comment(request, response, Reply)

        discussion_id = response.data['id']
        create_contribution.apply_async((Contribution.COMMENTER, {
            'app_label': 'discussion',
            'model': 'reply'
        }, request.user.id, unified_doc_id, discussion_id),
                                        priority=3,
                                        countdown=10)

        doc_type = get_doc_type_key(unified_document)
        reset_unified_document_cache(hub_ids=hubs,
                                     document_type=[doc_type, 'all'],
                                     filters=[DISCUSSED, TRENDING])

        return self.get_self_upvote_response(request, response, Reply)
def update_or_create_vote(request, user, paper, vote_type):
    vote = retrieve_vote(user, paper)

    if vote:
        vote.vote_type = vote_type
        vote.save()
        events_api.track_content_vote(user, vote, request)
        return get_vote_response(vote, 200)
    vote = create_vote(user, paper, vote_type)

    events_api.track_content_vote(user, vote, request)
    unified_doc_id = paper.unified_document.id
    create_contribution.apply_async(
        (
            Contribution.UPVOTER,
            {
                "app_label": "paper",
                "model": "vote"
            },
            user.id,
            unified_doc_id,
            vote.id,
        ),
        priority=3,
        countdown=10,
    )
    return get_vote_response(vote, 201)
def hypothesis_create_contribution(created, instance, sender, update_fields,
                                   **kwargs):
    if created:
        created_by = instance.created_by
        unified_doc_id = instance.unified_document.id
        create_contribution.apply_async((Contribution.SUBMITTER, {
            'app_label': 'hypothesis',
            'model': 'hypothesis'
        }, created_by.id, unified_doc_id, instance.id),
                                        priority=3,
                                        countdown=5)
Exemple #6
0
def update_or_create_vote(request, user, item, vote_type):
    cache_filters_to_reset = [TOP, TRENDING]
    if isinstance(item, (Thread, Comment, Reply)):
        cache_filters_to_reset = [TRENDING]

    hub_ids = [0]
    # NOTE: Hypothesis citations do not have a unified document attached
    has_unified_doc = hasattr(item, "unified_document")

    if has_unified_doc:
        hub_ids += list(item.unified_document.hubs.values_list("id", flat=True))

    vote = retrieve_vote(user, item)
    # TODO: calvinhlee - figure out how to handle contributions
    if vote is not None:
        vote.vote_type = vote_type
        vote.save(update_fields=["updated_date", "vote_type"])

        if has_unified_doc:
            doc_type = get_doc_type_key(item.unified_document)
            reset_unified_document_cache(
                hub_ids, document_type=[doc_type, "all"], filters=cache_filters_to_reset
            )

        # events_api.track_content_vote(user, vote, request)
        return get_vote_response(vote, 200)

    vote = create_vote(user, item, vote_type)
    if has_unified_doc:
        doc_type = get_doc_type_key(item.unified_document)
        reset_unified_document_cache(
            hub_ids, document_type=[doc_type, "all"], filters=cache_filters_to_reset
        )

    app_label = item._meta.app_label
    model = item._meta.model.__name__.lower()
    # events_api.track_content_vote(user, vote, request)
    create_contribution.apply_async(
        (
            Contribution.UPVOTER,
            {"app_label": app_label, "model": model},
            request.user.id,
            vote.unified_document.id,
            vote.id,
        ),
        priority=2,
        countdown=10,
    )
    return get_vote_response(vote, 201)
    def create(self, request, *args, **kwargs):
        model = request.path.split('/')[2]
        model_id = get_document_id_from_path(request)
        instance = RELATED_DISCUSSION_MODELS[model].objects.get(id=model_id)

        if model == 'citation':
            unified_document = instance.source
        else:
            unified_document = instance.unified_document

        if request.query_params.get('created_location') == 'progress':
            request.data['created_location'] = (
                BaseComment.CREATED_LOCATION_PROGRESS)

        response = super().create(request, *args, **kwargs)
        response = self.get_self_upvote_response(request, response, Thread)

        created_thread = Thread.objects.get(id=response.data['id'])
        if request.data.get('review'):
            created_thread.review_id = request.data.get('review')
            created_thread.save()

        hubs = list(unified_document.hubs.all().values_list('id', flat=True))
        discussion_id = response.data['id']

        self.sift_track_create_content_comment(request,
                                               response,
                                               Thread,
                                               is_thread=True)

        create_contribution.apply_async((Contribution.COMMENTER, {
            'app_label': 'discussion',
            'model': 'thread'
        }, request.user.id, unified_document.id, discussion_id),
                                        priority=1,
                                        countdown=10)

        doc_type = get_doc_type_key(unified_document)
        reset_unified_document_cache(
            hub_ids=hubs,
            document_type=[doc_type, 'all'],
            filters=[DISCUSSED, TRENDING],
        )

        return Response(self.serializer_class(created_thread).data,
                        status=status.HTTP_201_CREATED)
Exemple #8
0
def update_or_create_vote(request, user, summary, vote_type):
    vote = retrieve_vote(user, summary)

    if vote:
        vote.vote_type = vote_type
        vote.save(update_fields=['updated_date', 'vote_type'])
        events_api.track_content_vote(user, vote, request)
        return get_vote_response(vote, 200)

    vote = create_vote(user, summary, vote_type)
    events_api.track_content_vote(user, vote, request)
    create_contribution.apply_async((Contribution.UPVOTER, {
        'app_label': 'summary',
        'model': 'vote'
    }, user.id, summary.paper.unified_document.id, vote.id),
                                    priority=3,
                                    countdown=10)
    return get_vote_response(vote, 201)
Exemple #9
0
    def create(self, request):
        paper_id = request.data.get('paper')
        summary = self._create_summary(request)
        context = self.get_serializer_context()

        created = None
        if self._user_can_direct_edit(request.user):
            created = self._approve_and_add_summary_to_paper(
                paper_id, summary, request.user)
        self._invalidate_paper_cache(paper_id)
        update_or_create_vote(request, request.user, summary, Vote.UPVOTE)

        # TODO: Return old summary?
        # if created is not None and not created:
        #     summary = summary.paper.summary

        data = SummarySerializer(summary, context=context).data
        create_contribution.apply_async((Contribution.CURATOR, {
            'app_label': 'summary',
            'model': 'summary'
        }, request.user.id, paper_id, summary.id),
                                        priority=2,
                                        countdown=10)
        return Response(data, status=201)
    def create(self, request):
        user = request.user
        data = request.data

        amount = data['amount']
        purchase_method = data['purchase_method']
        purchase_type = data['purchase_type']
        content_type_str = data['content_type']
        object_id = data['object_id']
        transfer_rsc = False
        recipient = None

        if content_type_str not in self.ALLOWED_CONTENT_TYPES:
            return Response(status=400)

        if purchase_method not in (Purchase.OFF_CHAIN, Purchase.ON_CHAIN):
            return Response(status=400)

        decimal_amount = decimal.Decimal(amount)
        if decimal_amount <= 0:
            return Response(status=400)

        content_type = ContentType.objects.get(model=content_type_str)
        with transaction.atomic():
            if purchase_method == Purchase.ON_CHAIN:
                purchase = Purchase.objects.create(
                    user=user,
                    content_type=content_type,
                    object_id=object_id,
                    purchase_method=purchase_method,
                    purchase_type=purchase_type,
                    amount=amount)
            else:
                user_balance = user.get_balance()
                if user_balance - decimal_amount < 0:
                    return Response('Insufficient Funds', status=402)

                purchase = Purchase.objects.create(
                    user=user,
                    content_type=content_type,
                    object_id=object_id,
                    purchase_method=purchase_method,
                    purchase_type=purchase_type,
                    amount=amount,
                    paid_status=Purchase.PAID)

                source_type = ContentType.objects.get_for_model(purchase)
                Balance.objects.create(
                    user=user,
                    content_type=source_type,
                    object_id=purchase.id,
                    amount=f'-{amount}',
                )

            purchase_hash = purchase.hash()
            purchase.purchase_hash = purchase_hash
            purchase_boost_time = purchase.get_boost_time(amount)
            purchase.boost_time = purchase_boost_time
            purchase.group = purchase.get_aggregate_group()
            purchase.save()

            item = purchase.item
            context = {
                'purchase_minimal_serialization': True,
                'exclude_stats': True
            }

            #  transfer_rsc is set each time just in case we want
            #  to disable rsc transfer for a specific item
            if content_type_str == 'paper':
                paper = Paper.objects.get(id=object_id)
                unified_doc = paper.unified_document
                paper.calculate_hot_score()
                recipient = paper.uploaded_by
                cache_key = get_cache_key('paper', object_id)
                cache.delete(cache_key)
                transfer_rsc = True

                hub_ids = paper.hubs.values_list('id', flat=True)
                reset_unified_document_cache(
                    hub_ids,
                    document_type=['all', 'paper'],
                    filters=[TRENDING],
                )
            elif content_type_str == 'thread':
                transfer_rsc = True
                recipient = item.created_by
                unified_doc = item.unified_document
            elif content_type_str == 'comment':
                transfer_rsc = True
                unified_doc = item.unified_document
                recipient = item.created_by
            elif content_type_str == 'reply':
                transfer_rsc = True
                unified_doc = item.unified_document
                recipient = item.created_by
            elif content_type_str == 'summary':
                transfer_rsc = True
                recipient = item.proposed_by
                unified_doc = item.paper.unified_document
            elif content_type_str == 'bulletpoint':
                transfer_rsc = True
                recipient = item.created_by
                unified_doc = item.paper.unified_document
            elif content_type_str == 'researchhubpost':
                transfer_rsc = True
                recipient = item.created_by
                unified_doc = item.unified_document

                hub_ids = unified_doc.hubs.values_list('id', flat=True)
                reset_unified_document_cache(
                    hub_ids,
                    document_type=['all', 'posts'],
                    filters=[TRENDING],
                )

            if unified_doc.is_removed:
                return Response('Content is removed', status=403)

            if transfer_rsc and recipient and recipient != user:
                distribution = create_purchase_distribution(amount)
                distributor = Distributor(distribution, recipient, purchase,
                                          time.time())
                distributor.distribute()

        serializer = self.serializer_class(purchase, context=context)
        serializer_data = serializer.data

        if recipient and user:
            self.send_purchase_notification(purchase, unified_doc, recipient)
            self.send_purchase_email(purchase, recipient, unified_doc)

        create_contribution.apply_async((Contribution.SUPPORTER, {
            'app_label': 'purchase',
            'model': 'purchase'
        }, user.id, unified_doc.id, purchase.id),
                                        priority=2,
                                        countdown=10)
        return Response(serializer_data, status=201)
    def create(self, validated_data):
        request = self.context.get("request", None)
        if request:
            user = request.user
        else:
            user = None
        validated_data["uploaded_by"] = user

        if "url" in validated_data or "pdf_url" in validated_data:
            error = Exception("URL uploading is deprecated")
            sentry.log_error(error)
            raise error

        # Prepare validated_data by removing m2m
        authors = validated_data.pop("authors")
        hubs = validated_data.pop("hubs")
        hypothesis_id = validated_data.pop("hypothesis_id", None)
        citation_type = validated_data.pop("citation_type", None)
        file = validated_data.get("file")
        try:
            with transaction.atomic():
                # Temporary fix for updating read only fields
                # Not including file, pdf_url, and url because
                # those fields are processed
                for read_only_field in self.Meta.read_only_fields:
                    if read_only_field in validated_data:
                        validated_data.pop(read_only_field, None)

                # valid_doi = self._check_valid_doi(validated_data)
                # if not valid_doi:
                #     raise IntegrityError('DETAIL: Invalid DOI')

                self._add_url(file, validated_data)
                self._clean_abstract(validated_data)
                self._add_raw_authors(validated_data)

                paper = None

                if paper is None:
                    # It is important to note that paper signals
                    # are ran after call to super
                    paper = super(PaperSerializer, self).create(validated_data)
                    paper.full_clean(exclude=["paper_type"])

                unified_doc = paper.unified_document
                unified_doc_id = paper.unified_document.id
                if hypothesis_id:
                    self._add_citation(user, hypothesis_id, unified_doc,
                                       citation_type)

                paper_id = paper.id
                paper_title = paper.paper_title or ""
                file = paper.file
                self._check_pdf_title(paper, paper_title, file)
                # NOTE: calvinhlee - This is an antipattern. Look into changing
                Vote.objects.create(paper=paper,
                                    created_by=user,
                                    vote_type=Vote.UPVOTE)

                # Now add m2m values properly
                if validated_data["paper_type"] == Paper.PRE_REGISTRATION:
                    paper.authors.add(user.author_profile)

                # TODO: Do we still need add authors from the request content?
                paper.authors.add(*authors)

                self._add_orcid_authors(paper)
                paper.hubs.add(*hubs)
                for hub in hubs:
                    hub.paper_count = hub.get_paper_count()
                    hub.save(update_fields=["paper_count"])

                try:
                    self._add_file(paper, file)
                except Exception as e:
                    sentry.log_error(e, )

                paper.set_paper_completeness()
                # Fix adding references
                # self._add_references(paper)

                paper.pdf_license = paper.get_license(save=False)

                update_unified_document_to_paper(paper)

                tracked_paper = events_api.track_content_paper(
                    user, paper, request)
                update_user_risk_score(user, tracked_paper)

                create_contribution.apply_async(
                    (
                        Contribution.SUBMITTER,
                        {
                            "app_label": "paper",
                            "model": "paper"
                        },
                        user.id,
                        unified_doc_id,
                        paper_id,
                    ),
                    priority=3,
                    countdown=10,
                )

                celery_calculate_paper_twitter_score.apply_async((paper_id, ),
                                                                 priority=5,
                                                                 countdown=10)

                hub_ids = unified_doc.hubs.values_list("id", flat=True)
                if hub_ids.exists():
                    reset_unified_document_cache(
                        hub_ids,
                        document_type=["paper", "all"],
                        filters=[NEWEST],
                        with_default_hub=True,
                    )

                return paper
        except IntegrityError as e:
            sentry.log_error(e)
            raise e
        except Exception as e:
            error = PaperSerializerError(e, "Failed to create paper")
            sentry.log_error(error, base_error=error.trigger)
            raise error