Esempio n. 1
0
    def update_discussion_count(self):
        paper = self.paper
        if paper:
            new_dis_count = paper.get_discussion_count()
            paper.calculate_hot_score()

            paper.discussion_count = new_dis_count
            paper.save(update_fields=['discussion_count'])

            cache_key = get_cache_key('paper', paper.id)
            cache.delete(cache_key)

            for h in paper.hubs.all():
                h.discussion_count = h.get_discussion_count()
                h.save(update_fields=['discussion_count'])

            return new_dis_count

        post = self.post
        hypothesis = self.hypothesis
        instance = post or hypothesis
        if instance:
            new_dis_count = instance.get_discussion_count()
            instance.discussion_count = new_dis_count
            instance.save()
            return new_dis_count

        return 0
Esempio n. 2
0
    def get_hub_papers(self, request):
        # TODO: Delete this

        subscribed_hubs = request.GET.get("subscribed_hubs", False)
        external_source = request.GET.get("external_source", False)
        is_anonymous = request.user.is_anonymous
        if subscribed_hubs and not is_anonymous:
            return self.subscribed_hub_papers(request)

        page_number = int(request.GET["page"])
        start_date = datetime.datetime.fromtimestamp(
            int(request.GET.get("start_date__gte", 0)), datetime.timezone.utc)
        end_date = datetime.datetime.fromtimestamp(
            int(request.GET.get("end_date__lte", 0)), datetime.timezone.utc)
        ordering = self._set_hub_paper_ordering(request)
        hub_id = request.GET.get("hub_id", 0)

        cache_hit = None
        time_difference = end_date - start_date
        if page_number == 1 and "removed" not in ordering and not external_source:
            cache_pk = ""
            if time_difference.days > 365:
                cache_pk = f"{hub_id}_{ordering}_all_time"
            elif time_difference.days == 365:
                cache_pk = f"{hub_id}_{ordering}_year"
            elif time_difference.days == 30 or time_difference.days == 31:
                cache_pk = f"{hub_id}_{ordering}_month"
            elif time_difference.days == 7:
                cache_pk = f"{hub_id}_{ordering}_week"
            else:
                cache_pk = f"{hub_id}_{ordering}_today"

            cache_key_hub = get_cache_key("hub", cache_pk)
            cache_hit = cache.get(cache_key_hub)

            if cache_hit and page_number == 1:
                return Response(cache_hit)

        context = self.get_serializer_context()
        context["user_no_balance"] = True
        context["exclude_promoted_score"] = True
        context["include_wallet"] = False

        # if not cache_hit and page_number == 1:
        # reset_cache([hub_id], ordering, time_difference.days)

        papers = self._get_filtered_papers(hub_id, ordering)
        order_papers = self.calculate_paper_ordering(papers, ordering,
                                                     start_date, end_date)
        page = self.paginate_queryset(order_papers)
        serializer = HubPaperSerializer(page, many=True, context=context)
        serializer_data = serializer.data

        res = self.get_paginated_response({
            "data": serializer_data,
            "no_results": False,
            "feed_type": "all"
        })
        return res
Esempio n. 3
0
    def get_all_figures(self, request, pk=None):
        cache_key = get_cache_key("figure", pk)
        cache_hit = cache.get(cache_key)
        if cache_hit is not None:
            return Response({"data": cache_hit}, status=status.HTTP_200_OK)

        serializer_data = self.get_figures(pk)
        cache.set(cache_key, serializer_data, timeout=60 * 60 * 24 * 7)
        return Response({"data": serializer_data}, status=status.HTTP_200_OK)
Esempio n. 4
0
    def _get_unifed_document_cache_hit(self, document_type, filtering, hub_id,
                                       page_number, time_scope):
        cache_hit = None
        if page_number == 1 and 'removed' not in filtering:
            cache_pk = f'{document_type}_{hub_id}_{filtering}_{time_scope}'
            cache_key_hub = get_cache_key('hub', cache_pk)
            cache_hit = cache.get(cache_key_hub)

        if cache_hit:
            return cache_hit
        return None
Esempio n. 5
0
    def _get_latest_activity_cache_hit(self, request, hub_ids):
        hub_ids_list = hub_ids.split(",")
        if len(hub_ids_list) > 1:
            results = {}
            count = 0
            previous = ""
            next_url = request.build_absolute_uri()
            for hub_id in hub_ids_list:
                cache_key = get_cache_key("contributions", hub_id)
                cache_hit = cache.get(cache_key)
                if not cache_hit:
                    return None

                for hit in cache_hit["results"]:
                    hit_id = hit["id"]
                    if hit_id not in results:
                        results[hit_id] = hit
                count += cache_hit.get("count", 1)

            results = list(results.values())
            results = sorted(results,
                             key=lambda contrib: contrib["created_date"],
                             reverse=True)[:10]
            next_url = replace_query_param(next_url, "page", 2)

            data = {
                "count": count,
                "next": next_url,
                "previous": previous,
                "results": results,
            }
            return data
        else:
            cache_key = get_cache_key("contributions", hub_ids)
            cache_hit = cache.get(cache_key)
            return cache_hit
Esempio n. 6
0
 def dispatch(self, request, *args, **kwargs):
     query_params = request.META.get('QUERY_STRING', '')
     if 'score' in query_params:
         cache_key = get_cache_key('hubs', 'trending')
         cache_hit = cache.get(cache_key)
         if cache_hit:
             return cache_hit
         else:
             response = super().dispatch(request, *args, **kwargs)
             response.render()
             cache.set(cache_key, response, timeout=60 * 60 * 24 * 7)
             return response
     else:
         response = super().dispatch(request, *args, **kwargs)
     return response
Esempio n. 7
0
def invalidate_most_discussed_cache(
    hub_ids,
    document_types=CACHE_DOCUMENT_TYPES,
    date_ranges=CACHE_DATE_RANGES,
    with_default=True
):
    if with_default:
        hub_ids = add_default_hub(hub_ids)

    for hub_id in hub_ids:
        for date_range in date_ranges:
            for doc_type in document_types:
                cache_key = get_cache_key(
                    'hub',
                    f'{doc_type}_{hub_id}_-discussed_{date_range}'
                )
                cache.delete(cache_key)
Esempio n. 8
0
    def retrieve(self, request, *args, **kwargs):
        instance = self.get_object()
        context = {"request": request, "get_raw_author_scores": True}
        cache_key = get_cache_key("paper", instance.id)
        cache_hit = cache.get(cache_key)
        if cache_hit is not None:
            vote = self.serializer_class(
                context=context).get_user_vote(instance)
            cache_hit["user_vote"] = vote
            return Response(cache_hit)

        if request.query_params.get("make_public") and not instance.is_public:
            instance.is_public = True
            instance.save()
        serializer = self.serializer_class(instance, context=context)
        serializer_data = serializer.data

        cache.set(cache_key, serializer_data, timeout=60 * 60 * 24 * 7)
        return Response(serializer_data)
Esempio n. 9
0
    def censor(self, request, pk=None):
        paper = self.get_object()
        paper_id = paper.id
        unified_doc = paper.unified_document
        cache_key = get_cache_key("paper", paper_id)
        cache.delete(cache_key)
        hub_ids = list(paper.hubs.values_list("id", flat=True))

        content_id = f"{type(paper).__name__}_{paper_id}"
        user = request.user
        content_creator = paper.uploaded_by
        if content_creator:
            events_api.track_flag_content(content_creator, content_id, user.id)
            decisions_api.apply_bad_content_decision(content_creator,
                                                     content_id,
                                                     "MANUAL_REVIEW", user)
            decisions_api.apply_bad_user_decision(content_creator,
                                                  "MANUAL_REVIEW", user)

        Contribution.objects.filter(unified_document=unified_doc).delete()
        paper.is_removed = True
        paper.save()
        censored_paper_cleanup.apply_async((paper_id, ), priority=3)

        unified_document = paper.unified_document
        unified_document.is_removed = True
        unified_document.save()

        reset_unified_document_cache(
            hub_ids,
            filters=[TRENDING, TOP, DISCUSSED, NEWEST],
            document_type=["all", "paper"],
            with_default_hub=True,
        )

        return Response("Paper was deleted.", status=200)
Esempio n. 10
0
def preload_latest_activity(hub_ids, ordering):
    from user.views import UserViewSet
    from reputation.serializers import DynamicContributionSerializer

    hub_ids_str = hub_ids
    request_path = '/api/user/following_latest_activity/'
    if STAGING:
        http_host = 'staging-backend.researchhub.com'
        protocol = 'https'
    elif PRODUCTION:
        http_host = 'backend.researchhub.com'
        protocol = 'https'
    else:
        http_host = 'localhost:8000'
        protocol = 'http'

    query_string = f'?page=1&hub_ids={hub_ids_str}'
    http_meta = {
        'QUERY_STRING': query_string,
        'HTTP_HOST': http_host,
        'HTTP_X_FORWARDED_PROTO': protocol,
    }

    cache_key = get_cache_key('contributions', hub_ids_str)
    user_view = UserViewSet()
    http_req = HttpRequest()
    http_req.META = http_meta
    http_req.path = request_path
    req = Request(http_req)
    user_view.request = req

    latest_activities = user_view._get_latest_activity_queryset(
        hub_ids_str,
        ordering
    )
    page = user_view.paginate_queryset(latest_activities)
    context = user_view._get_latest_activity_context()
    serializer = DynamicContributionSerializer(
        page,
        _include_fields=[
            'contribution_type',
            'created_date',
            'id',
            'source',
            'unified_document',
            'user'
        ],
        context=context,
        many=True,
    )
    serializer_data = serializer.data

    paginated_response = user_view.get_paginated_response(
        serializer_data
    )

    cache.set(
        cache_key,
        paginated_response.data,
        timeout=60*60*24
    )

    return paginated_response.data
Esempio n. 11
0
def preload_trending_documents(
    document_type,
    hub_id,
    filtering,
    time_scope,
):
    from researchhub_document.views import ResearchhubUnifiedDocumentViewSet
    from researchhub_document.serializers import (
        DynamicUnifiedDocumentSerializer)

    if time_scope == 'all_time':
        cache_pk = f'{document_type}_{hub_id}_{filtering}_all_time'
    elif time_scope == 'year':
        cache_pk = f'{document_type}_{hub_id}_{filtering}_year'
    elif time_scope == 'month':
        cache_pk = f'{document_type}_{hub_id}_{filtering}_month'
    elif time_scope == 'week':
        cache_pk = f'{document_type}_{hub_id}_{filtering}_week'
    else:  # Today
        cache_pk = f'{document_type}_{hub_id}_{filtering}_today'

    query_string_filtering = 'top_rated'
    if filtering == 'removed':
        query_string_filtering = 'removed'
    elif filtering == '-score':
        query_string_filtering = 'top_rated'
    elif filtering == '-discussed':
        query_string_filtering = 'most_discussed'
    elif filtering == '-created_date':
        query_string_filtering = 'newest'
    elif filtering == '-hot_score':
        query_string_filtering = 'hot'

    request_path = '/api/paper/get_hub_papers/'
    if STAGING:
        http_host = 'staging-backend.researchhub.com'
        protocol = 'https'
    elif PRODUCTION:
        http_host = 'backend.researchhub.com'
        protocol = 'https'
    else:
        http_host = 'localhost:8000'
        protocol = 'http'

    query_string = 'page=1&time={}&ordering={}&hub_id={}&'.format(
        time_scope, query_string_filtering, hub_id)
    http_meta = {
        'QUERY_STRING': query_string,
        'HTTP_HOST': http_host,
        'HTTP_X_FORWARDED_PROTO': protocol,
    }

    document_view = ResearchhubUnifiedDocumentViewSet()
    http_req = HttpRequest()
    http_req.META = http_meta
    http_req.path = request_path
    req = Request(http_req)
    document_view.request = req

    documents = document_view.get_filtered_queryset(document_type, filtering,
                                                    hub_id, time_scope)
    page = document_view.paginate_queryset(documents)
    context = document_view._get_serializer_context()
    serializer = DynamicUnifiedDocumentSerializer(
        page,
        _include_fields=[
            'created_by',
            'created_date',
            'documents',
            'document_type',
            'hot_score',
            'hot_score_v2',
            'reviews',
            'score',
            'id',
        ],
        many=True,
        context=context,
    )
    serializer_data = serializer.data

    paginated_response = document_view.get_paginated_response(serializer_data)

    cache_key_hub = get_cache_key('hub', cache_pk)
    cache.set(cache_key_hub, paginated_response.data, timeout=None)

    return paginated_response.data
Esempio n. 12
0
 def _invalidate_paper_cache(self, paper_id):
     cache_key = get_cache_key('paper', paper_id)
     cache.delete(cache_key)
Esempio n. 13
0
    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)
Esempio n. 14
0
    def subscribed_hub_papers(self, request):
        feed_type = "subscribed"
        user = request.user
        hubs = user.subscribed_hubs.all()
        page_number = int(request.GET["page"])
        start_date = datetime.datetime.fromtimestamp(
            int(request.GET.get("start_date__gte", 0)), datetime.timezone.utc)
        end_date = datetime.datetime.fromtimestamp(
            int(request.GET.get("end_date__lte", 0)), datetime.timezone.utc)
        ordering = self._set_hub_paper_ordering(request)

        if ordering == "-hot_score" and page_number == 1:
            papers = {}
            for hub in hubs.iterator():
                hub_name = hub.slug
                cache_key = get_cache_key("papers", hub_name)
                cache_hit = cache.get(cache_key)
                if cache_hit:
                    for hit in cache_hit:
                        paper_id = hit["id"]
                        abstract = hit.get("abstract", None)
                        if paper_id not in papers and abstract:
                            papers[paper_id] = hit
            papers = list(papers.values())

            if len(papers) < 1:
                qs = self.get_queryset(
                    include_autopull=True).order_by("-hot_score")
                papers = qs.filter(hubs__in=hubs).distinct()
            else:
                papers = sorted(papers, key=lambda paper: -paper["hot_score"])
                papers = papers[:UNIFIED_DOC_PAGE_SIZE]
                next_page = request.build_absolute_uri()
                if len(papers) < UNIFIED_DOC_PAGE_SIZE:
                    next_page = None
                else:
                    next_page = replace_query_param(next_page, "page", 2)
                res = {
                    "count": len(papers),
                    "next": next_page,
                    "results": {
                        "data": papers,
                        "no_results": False,
                        "feed_type": feed_type,
                    },
                }
                return Response(res, status=status.HTTP_200_OK)

        else:
            qs = self.get_queryset(
                include_autopull=True).order_by("-hot_score")
            papers = qs.filter(hubs__in=hubs).distinct()

        if papers.count() < 1:
            log_info(f"""
                    No hub papers found, retrieiving trending papers.
                    Page: {page_number}
                """)
            trending_pk = "0_-hot_score_today"
            cache_key_hub = get_cache_key("hub", trending_pk)
            cache_hit = cache.get(cache_key_hub)

            if cache_hit and page_number == 1:
                return Response(cache_hit)

            feed_type = "all"
            papers = self.get_queryset().order_by("-hot_score")

        context = self.get_serializer_context()
        context["user_no_balance"] = True
        context["exclude_promoted_score"] = True
        context["include_wallet"] = False

        order_papers = self.calculate_paper_ordering(papers, ordering,
                                                     start_date, end_date)

        page = self.paginate_queryset(order_papers)
        serializer = HubPaperSerializer(page, many=True, context=context)
        serializer_data = serializer.data

        return self.get_paginated_response({
            "data": serializer_data,
            "no_results": False,
            "feed_type": feed_type
        })