def test_get_judgement_queue_deleted(self): uploader = Generators.user() submitter = Generators.user(groups=['iotd_submitters']) submitter2 = Generators.user(groups=['iotd_submitters']) reviewer = Generators.user(groups=['iotd_reviewers']) reviewer2 = Generators.user(groups=['iotd_reviewers']) Generators.premium_subscription(uploader, "AstroBin Ultimate 2020+") image = Generators.image(user=uploader) image.designated_iotd_submitters.add(submitter, submitter2) image.designated_iotd_reviewers.add(reviewer, reviewer2) IotdSubmission.objects.create(submitter=submitter, image=image) IotdSubmission.objects.create(submitter=submitter2, image=image) IotdVote.objects.create(reviewer=reviewer, image=image) IotdVote.objects.create(reviewer=reviewer2, image=image) image.delete() self.assertEquals(0, len(IotdService().get_judgement_queue()))
def may_submit_to_iotd_tp_process_reason(user: User, image: Image) -> str: may, reason = IotdService.may_submit_to_iotd_tp_process(user, image) return reason
def astrobin_image(context, image, alias, **kwargs): request = kwargs.get('request', context['request']) revision_label = kwargs.get('revision', 'final') url_size = kwargs.get('url_size', 'regular') url_revision = kwargs.get('url_revision', revision_label) link = kwargs.get('link', True) link_alias = kwargs.get('link_alias', alias) tooltip = kwargs.get('tooltip', True) nav_ctx = kwargs.get('nav_ctx', request.GET.get('nc', context.get('nav_ctx'))) nav_ctx_extra = kwargs.get('nav_ctx_extra', request.GET.get('nce', context.get('nav_ctx_extra'))) classes = kwargs.get('classes', '') instant = kwargs.get('instant', False) fancybox = kwargs.get('fancybox', False) rel = kwargs.get('rel', '') if nav_ctx == 'user': # None is considered to be default for 'user' nav_ctx = None response_dict = { 'provide_size': True, } if alias == '': alias = 'gallery' if link_alias in ('gallery_inverted', 'regular_inverted', 'hd_inverted', 'real_inverted'): mod = 'inverted' else: mod = None size = settings.THUMBNAIL_ALIASES[''][alias]['size'] if image is None or not isinstance(image, Image): return { 'status': 'failure', 'image': '', 'alias': alias, 'revision': revision_label, 'revision_title': None, 'size_x': size[0], 'size_y': size[1], 'caption_cache_key': 'astrobin_image_no_image', 'nav_ctx': nav_ctx, 'nav_ctx_extra': nav_ctx_extra, 'classes': classes, 'is_revision': False, 'instant': False, 'fancybox': False, 'fancybox_url': None, 'rel': rel, } # Old images might not have a size in the database, let's fix it. image_revision = image if revision_label not in [0, '0', 'final']: try: image_revision = image.revisions.get(label=revision_label) except ImageRevision.DoesNotExist: # Image revision was deleted pass w = image_revision.w h = image_revision.h if w == 0 or h == 0 or w is None or h is None: try: from django.core.files.images import get_image_dimensions (w, h) = get_image_dimensions(image_revision.image_file.file) if w and h: image_revision.w = w image_revision.h = h image_revision.save(keep_deleted=True) else: logger.warning("astrobin_image tag: unable to get image dimensions for revision %d: %s" % ( image_revision.pk)) response_dict['status'] = 'error' response_dict['error_message'] = _("Data corruption. Please upload this image again. Sorry!") except (IOError, ValueError, DecompressionBombError) as e: w = size[0] h = size[1] if size[1] > 0 else w logger.warning("astrobin_image tag: unable to get image dimensions for revision %d: %s" % ( image_revision.pk, str(e))) response_dict['status'] = 'error' response_dict['error_message'] = _("Data corruption. Please upload this image again. Sorry!") except (TypeError, zlib.error) as e: w = size[0] h = size[1] if size[1] > 0 else w logger.warning("astrobin_image tag: unable to get image dimensions for revision %d: %s" % ( image_revision.pk, str(e))) if alias in ( 'regular', 'regular_inverted', 'regular_sharpened', 'regular_large', 'regular_large_inverted', 'regular_large_sharpened', 'hd', 'hd_inverted', 'hd_sharpened', 'real', 'real_inverted' ): size = (size[0], int(size[0] / (w / float(h)))) response_dict['provide_size'] = False placehold_size = [size[0], size[1]] for i in range(0, 2): if placehold_size[i] > 1920: placehold_size[i] = 1920 if w is not None and w < placehold_size[0]: placehold_size[0] = w placehold_size[1] = h # Determine whether this is an animated gif, and we should show it as such field = image.get_thumbnail_field(revision_label) if not field.name.startswith('images/'): field.name = 'images/' + field.name animated = field.name.lower().endswith('.gif') and \ alias in ( 'regular', 'regular_sharpened', 'regular_large', 'regular_large_sharpened', 'hd', 'hd_sharpened', 'real') url = get_image_url(image, url_revision, url_size) url_hd = get_image_url(image, url_revision, 'full') show_tooltip = tooltip and (alias in ( 'gallery', 'gallery_inverted', 'thumb', )) ########## # BADGES # ########## badges = [] if alias in ( 'thumb', 'gallery', 'gallery_inverted', 'regular', 'regular_inverted', 'regular_sharpened', 'regular_large', 'regular_large_inverted', 'regular_large_sharpened', ): if IotdService().is_iotd(image): badges.append('iotd') elif IotdService().is_top_pick(image): badges.append('top-pick') elif IotdService().is_top_pick_nomination(image): badges.append('top-pick-nomination') elif image.is_wip: badges.append('wip') # Temporarily disable this because it hogs the default celery queue. """ cache_key = 'top100_ids' top100_ids = cache.get(cache_key) if top100_ids is None: from astrobin.tasks import update_top100_ids update_top100_ids.delay() elif image.pk in top100_ids: badges.append('top100') """ cache_key = image.thumbnail_cache_key(field, alias, revision_label) if animated: cache_key += '_animated' thumb_url = cache.get(cache_key) # Force HTTPS if thumb_url and request.is_secure(): thumb_url = thumb_url.replace('http://', 'https://', 1) # If we're testing, we want to bypass the placeholder thing and force-get # the thumb url. if thumb_url is None and settings.TESTING: thumb = image.thumbnail_raw(alias, revision_label) if thumb: thumb_url = thumb.url get_thumb_url = None if thumb_url is None: get_thumb_kwargs = { 'id': image.hash if image.hash else image.id, 'alias': alias, } if revision_label is None or revision_label != 'final': get_thumb_kwargs['r'] = revision_label get_thumb_url = reverse('image_thumb', kwargs=get_thumb_kwargs) if animated: get_thumb_url += '?animated' get_regular_large_thumb_url, regular_large_thumb_url = ImageService(image).get_enhanced_thumb_url( field, alias, revision_label, animated, request.is_secure(), 'regular_large') get_enhanced_thumb_url, enhanced_thumb_url = ImageService(image).get_enhanced_thumb_url( field, alias, revision_label, animated, request.is_secure(), 'hd') # noinspection PyTypeChecker return dict(list(response_dict.items()) + list({ 'status': 'success', 'image': image, 'alias': alias, 'mod': mod, 'revision': revision_label, 'size_x': size[0], 'size_y': size[1], 'placehold_size': "%sx%s" % (placehold_size[0], placehold_size[1]), 'real': alias in ('real', 'real_inverted'), 'url': url, 'url_hd': url_hd, 'show_tooltip': show_tooltip, 'request': request, 'caption_cache_key': "%d_%s_%s_%s" % ( image.id, revision_label, alias, request.LANGUAGE_CODE if hasattr(request, "LANGUAGE_CODE") else "en"), 'badges': badges, 'animated': animated, 'get_thumb_url': get_thumb_url, 'thumb_url': thumb_url, 'link': link, 'nav_ctx': nav_ctx, 'nav_ctx_extra': nav_ctx_extra, 'classes': classes, 'enhanced_thumb_url': enhanced_thumb_url, 'get_enhanced_thumb_url': get_enhanced_thumb_url, 'regular_large_thumb_url': regular_large_thumb_url, 'get_regular_large_thumb_url': get_regular_large_thumb_url, 'is_revision': hasattr(image_revision, 'label'), 'revision_id': image_revision.pk, 'revision_title': image_revision.title if hasattr(image_revision, 'label') else None, 'w': w, 'h': h, 'instant': instant, 'fancybox': fancybox, 'fancybox_url': reverse('image_rawthumb', kwargs={ 'id': image.get_id(), 'alias': 'hd', 'r': revision_label, }) + '?sync', 'rel': rel, }.items()))
def get_queryset(self): return IotdService().get_iotds()
def items(self): return IotdService().get_top_picks()[:10]
def next_available_selection_time(self, request): return JsonResponse({ 'nextAvailableSelectionTime': IotdService().get_next_available_selection_time_for_judge( request.user).isoformat() + 'Z' })
def get_queryset(self): return IotdService().get_judgement_queue( self.request.user, self.request.GET.get('sort', None), )
def get_queryset(self): queryset = IotdService().get_top_pick_nominations() queryset = self.filter_by_datasource(queryset) queryset = self.filter_by_acquisition_type(queryset) return queryset
def update_top_pick_nomination_archive(): IotdService().update_top_pick_nomination_archive()
def update_judgement_queues(): IotdService().update_judgement_queues() logger.info("update_judgement_queues completed")
def update_review_queues(): IotdService().update_review_queues() logger.info("update_review_queues completed")
def update_submission_queues(): IotdService().update_submission_queues() logger.info("update_submission_queues completed")
def test_is_top_pick_nomination_false_still_in_queue(self): image = Generators.image() Generators.premium_subscription(image.user, 'AstroBin Ultimate 2020+') IotdGenerators.submission(image=image) self.assertFalse(IotdService().is_top_pick_nomination(image))
def prepare_top_picks(self, obj): return IotdService().get_top_picks().filter(user=obj).count()
def prepare_is_top_pick(self, obj): return IotdService().is_top_pick( obj) and not IotdService().is_iotd(obj)
def update_top_pick_archive(): IotdService().update_top_pick_archive()
def prepare_is_top_pick_nomination(self, obj): return IotdService().is_top_pick_nomination(obj) and \ not IotdService().is_top_pick(obj) and \ not IotdService().is_iotd(obj)
def image_post_save(sender, instance, created, **kwargs): # type: (object, Image, bool, object) -> None if created: instance.user.userprofile.premium_counter += 1 instance.user.userprofile.save(keep_deleted=True) if not instance.is_wip: if not instance.skip_notifications: push_notification_for_new_image.apply_async(args=( instance.user.pk, instance.pk, )) if instance.moderator_decision == 1: add_story(instance.user, verb='VERB_UPLOADED_IMAGE', action_object=instance) if Image.all_objects.filter(user=instance.user).count() == 1: push_notification( [instance.user], None, 'congratulations_for_your_first_image', { 'BASE_URL': settings.BASE_URL, 'PREMIUM_MAX_IMAGES_FREE': settings.PREMIUM_MAX_IMAGES_FREE, 'url': reverse_url('image_detail', args=(instance.get_id(), )) }) mentions = MentionsService.get_mentions(instance.description_bbcode) else: mentions = cache.get("image.%d.image_pre_save_mentions" % instance.pk, []) for username in mentions: user = get_object_or_None(User, username=username) if not user: try: profile = get_object_or_None(UserProfile, real_name=username) if profile: user = profile.user except MultipleObjectsReturned: user = None if user and user != instance.user: thumb = instance.thumbnail_raw('gallery', None, sync=True) push_notification( [user], instance.user, 'new_image_description_mention', { 'image': instance, 'image_thumbnail': thumb.url if thumb else None, 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), }) if not instance.uploader_in_progress: groups = instance.user.joined_group_set.filter(autosubmission=True) for group in groups: if instance.is_wip: group.images.remove(instance) else: group.images.add(instance) if instance.user.userprofile.updated < datetime.datetime.now( ) - datetime.timedelta(minutes=5): instance.user.save() try: instance.user.userprofile.save(keep_deleted=True) except UserProfile.DoesNotExist: pass UserService(instance.user).clear_gallery_image_list_cache() if instance.user.userprofile.auto_submit_to_iotd_tp_process: IotdService.submit_to_iotd_tp_process(instance.user, instance, False)
def get_queryset(self): return IotdService().get_submission_queue(self.request.user)
def get_queryset(self): return IotdService().get_submission_queue( self.request.user, self.request.GET.get('sort', None), )
def cannot_select_now_reason(self, request): return JsonResponse({ 'reason': IotdService().judge_cannot_select_now_reason(request.user) })
def get_queryset(self): return IotdService().get_review_queue(self.request.user)
def test_user_profile_banned_from_competitions(self, retrieve_primary_thumbnails): self.client.login(username="******", password="******") self._do_upload('astrobin/fixtures/test.jpg') self.client.logout() image = Image.objects_including_wip.all()[0] submitter = User.objects.create_user('submitter', '*****@*****.**', 'password') submitter2 = User.objects.create_user('submitter2', '*****@*****.**', 'password') submitters = Group.objects.create(name='iotd_submitters') submitters.user_set.add(submitter, submitter2) reviewer = User.objects.create_user('reviewer', '*****@*****.**', 'password') reviewer2 = User.objects.create_user('reviewer2', '*****@*****.**', 'password') reviewers = Group.objects.create(name='iotd_reviewers') reviewers.user_set.add(reviewer, reviewer2) judge = User.objects.create_user('judge', '*****@*****.**', 'password') judges = Group.objects.create(name='iotd_judges') judges.user_set.add(judge) IotdSubmission.objects.create(submitter=submitter, image=image) IotdSubmission.objects.create(submitter=submitter2, image=image) IotdVote.objects.create(reviewer=reviewer, image=image) vote = IotdVote.objects.create(reviewer=reviewer2, image=image) iotd = Iotd.objects.create(judge=judge, image=image, date=datetime.now().date()) image.published = datetime.now() - timedelta(settings.IOTD_REVIEW_WINDOW_DAYS) - timedelta(hours=1) image.save() profile = self.user.userprofile profile.banned_from_competitions = datetime.now() profile.save(keep_deleted=True) image = Image.objects_including_wip.get(pk=image.pk) TopPickArchive.objects.all().delete() TopPickNominationsArchive.objects.all().delete() IotdService().update_top_pick_nomination_archive() IotdService().update_top_pick_archive() # Check that the IOTD banner is still visible because the ban is not retroactive. response = self.client.get(reverse('image_detail', args=(image.get_id(),))) self.assertContains(response, "iotd-ribbon") # Check that the IOTD badge is still not visible because the ban is not retroactive. response = self.client.get(reverse('user_page', args=(self.user.username,))) self.assertContains(response, 'iotd-badge') # Check that the Top pick badge is still visible because the ban is not retroactive. iotd.delete() TopPickArchive.objects.all().delete() TopPickNominationsArchive.objects.all().delete() IotdService().update_top_pick_nomination_archive() IotdService().update_top_pick_archive() response = self.client.get(reverse('user_page', args=(self.user.username,))) self.assertContains(response, 'top-pick-badge') # Check that the Top pick nomination badge is still visible because the ban is not retroactive. IotdVote.objects.all().delete() TopPickArchive.objects.all().delete() TopPickNominationsArchive.objects.all().delete() IotdService().update_top_pick_nomination_archive() IotdService().update_top_pick_archive() response = self.client.get(reverse('user_page', args=(self.user.username,))) self.assertContains(response, 'top-pick-nomination-badge')
def prepare_top_pick_nominations(self, obj): return IotdService().get_top_pick_nominations().filter( image__user=obj).count()
def test_vote_model(self): Generators.premium_subscription(self.image.user, "AstroBin Ultimate 2020+") submission_1 = IotdSubmission.objects.create( submitter=self.submitter_1, image=self.image) IotdSubmission.objects.create( submitter=self.submitter_2, image=self.image) vote = IotdVote.objects.create( reviewer=self.reviewer_1, image=submission_1.image) self.assertEqual(vote.reviewer, self.reviewer_1) self.assertEqual(vote.image, submission_1.image) self.image.published = datetime.now() - timedelta(settings.IOTD_REVIEW_WINDOW_DAYS) - timedelta(hours=1) self.image.save() IotdService().update_top_pick_archive() # Badge is not present with just one vote response = self.client.get(reverse_lazy('image_detail', args=(self.image.get_id(),))) self.assertNotContains(response, 'top-pick-badge') # Image is not in Top Picks page with just one vote response = self.client.get(reverse_lazy('top_picks')) self.assertNotContains(response, self.image.title) cache.clear() self.image.published = datetime.now() self.image.save() IotdVote.objects.create( reviewer=self.reviewer_2, image=submission_1.image) self.image.published = datetime.now() - timedelta(settings.IOTD_REVIEW_WINDOW_DAYS) - timedelta(hours=1) self.image.save() IotdService().update_top_pick_archive() # Badge is present response = self.client.get(reverse_lazy('image_detail', args=(self.image.get_id(),))) self.assertContains(response, 'top-pick-badge') # Image is in Top Picks page response = self.client.get(reverse_lazy('top_picks')) self.assertContains(response, self.image.title) cache.clear() iotd = Iotd.objects.create( judge=self.judge_1, image=self.image, date=datetime.now().date() + timedelta(1)) IotdService().update_top_pick_archive() # Badge is still present if image is future IOTD response = self.client.get(reverse_lazy('image_detail', args=(self.image.get_id(),))) self.assertContains(response, 'top-pick-badge') # Image is still in Top Picks page response = self.client.get(reverse_lazy('top_picks')) self.assertContains(response, self.image.title) cache.clear() # Badge is gone if image is present IOTD Iotd.objects.filter(pk=iotd.pk).update(date=datetime.now().date()) IotdService().update_top_pick_archive() response = self.client.get(reverse_lazy('image_detail', args=(self.image.get_id(),))) self.assertNotContains(response, 'top-pick-badge') # Image is still from Top Picks page. It did earn that badge after all response = self.client.get(reverse_lazy('top_picks')) self.assertContains(response, self.image.title) cache.clear() # Badge is gone is image is past IOTD Iotd.objects.filter(pk=iotd.pk).update(date=datetime.now().date() - timedelta(1)) IotdService().update_top_pick_archive() response = self.client.get(reverse_lazy('image_detail', args=(self.image.get_id(),))) self.assertNotContains(response, 'top-pick-badge') # Image is still not gone from Top Picks page response = self.client.get(reverse_lazy('top_picks')) self.assertContains(response, self.image.title) cache.clear() iotd.delete() # Image must not be past IOTD iotd = Iotd.objects.create( judge=self.judge_1, image=self.image, date=datetime.now().date() - timedelta(1)) with self.assertRaisesRegex(ValidationError, "already been an IOTD"): IotdVote.objects.create( reviewer=self.reviewer_2, image=self.image) iotd.delete() # Cannot vote again for the same with self.assertRaisesRegex(ValidationError, "already exists"): IotdVote.objects.create( reviewer=self.reviewer_1, image=submission_1.image) # Test max daily image2 = Image.objects.create(user=self.user) submission_2 = IotdSubmission.objects.create( submitter=self.submitter_2, image=image2) with self.assertRaisesRegex(ValidationError, "already voted.*today"): with self.settings(IOTD_REVIEW_MAX_PER_DAY=1): IotdVote.objects.create( reviewer=self.reviewer_1, image=submission_2.image)
def prepare_iotds(self, obj): return IotdService().get_iotds().filter(image__user=obj).count()
def get_queryset(self): return IotdService().get_judgement_queue()
def prepare_is_iotd(self, obj): return IotdService().is_iotd(obj)
def test_top_picks_data_source_filter(self): IotdSubmission.objects.create(submitter=self.submitter, image=self.image) IotdSubmission.objects.create(submitter=self.submitter2, image=self.image) IotdVote.objects.create(reviewer=self.reviewer, image=self.image) IotdVote.objects.create(reviewer=self.reviewer2, image=self.image) self.image.published = datetime.now() - timedelta( settings.IOTD_REVIEW_WINDOW_DAYS) - timedelta(hours=1) self.image.save() IotdService().update_top_pick_archive() response = self.client.get(reverse_lazy('top_picks')) self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=backyard') self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=traveller') self.assertNotContains(response, self.image.title) self.image.data_source = 'TRAVELLER' self.image.save(keep_deleted=True) response = self.client.get( reverse_lazy('top_picks') + '?source=traveller') self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=backyard') self.assertNotContains(response, self.image.title) self.image.data_source = 'OWN_REMOTE' self.image.save(keep_deleted=True) response = self.client.get( reverse_lazy('top_picks') + '?source=own-remote') self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=traveller') self.assertNotContains(response, self.image.title) self.image.data_source = 'AMATEUR_HOSTING' self.image.save(keep_deleted=True) response = self.client.get( reverse_lazy('top_picks') + '?source=amateur-hosting') self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=own-remote') self.assertNotContains(response, self.image.title) self.image.data_source = 'PUBLIC_AMATEUR_DATA' self.image.save(keep_deleted=True) response = self.client.get( reverse_lazy('top_picks') + '?source=public-amateur-data') self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=amateur-hosting') self.assertNotContains(response, self.image.title) self.image.data_source = 'PRO_DATA' self.image.save(keep_deleted=True) response = self.client.get( reverse_lazy('top_picks') + '?source=pro-data') self.assertContains(response, self.image.title) response = self.client.get( reverse_lazy('top_picks') + '?source=public-amateur-data') self.assertNotContains(response, self.image.title)
def get_next_available_selection_time_for_judge(judge): # type: (User) -> datetime return IotdService().get_next_available_selection_time_for_judge(judge)