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
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
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)
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
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
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
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)
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)
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)
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
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
def _invalidate_paper_cache(self, paper_id): cache_key = get_cache_key('paper', paper_id) cache.delete(cache_key)
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 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 })