def notify_subscribers(): push_notification( list(instance.topic.subscribers.exclude(pk=instance.user.pk)), instance.user, 'new_forum_reply', { 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url('user_page', kwargs={'username': instance.user}), 'post_url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'topic_url': build_notification_url( settings.BASE_URL + instance.topic.get_absolute_url(), instance.user), 'topic_name': instance.topic.name, 'unsubscribe_url': build_notification_url( settings.BASE_URL + reverse_url('pybb:delete_subscription', args=[instance.topic.id]), instance.user) })
def forum_topic_pre_save(sender, instance, **kwargs): if not hasattr(instance.forum, 'group'): return try: topic = sender.objects.get(pk=instance.pk) except sender.DoesNotExist: pass else: if topic.on_moderation == True and instance.on_moderation == False: # This topic is being approved group = instance.forum.group push_notification( [x for x in group.members.all() if x != instance.user], instance.user, 'new_topic_in_group', { 'user': instance.user.userprofile.get_display_name(), 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'group_url': build_notification_url( reverse_url('group_detail', kwargs={'pk': group.pk}), instance.user), 'group_name': group.name, 'topic_title': instance.name, }, )
def notify_subscribers(mentions): # type: (List[str]) -> None recipients = list( instance.topic.subscribers.exclude(pk__in=list( set([instance.user.pk] + [ x.pk for x in MentionsService. get_mentioned_users_with_notification_enabled( mentions, 'new_forum_post_mention') ])))) if recipients: push_notification( recipients, instance.user, 'new_forum_reply', { 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), 'post_url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'topic_url': build_notification_url( settings.BASE_URL + instance.topic.get_absolute_url(), instance.user), 'topic_name': instance.topic.name, 'unsubscribe_url': build_notification_url( settings.BASE_URL + reverse_url('pybb:delete_subscription', args=[instance.topic.id]), instance.user) })
def reject(self, request, pk): edit_proposal: EquipmentItemEditProposalMixin = get_object_or_404( self.get_serializer().Meta.model, pk=pk) check_permissions, response = self.check_edit_proposal_permissions( request, edit_proposal) if not check_permissions: return response edit_proposal.edit_proposal_reviewed_by = request.user edit_proposal.edit_proposal_review_ip = request.META.get('REMOTE_ADDR') edit_proposal.edit_proposal_review_timestamp = timezone.now() edit_proposal.edit_proposal_review_comment = request.data.get( 'comment') edit_proposal.edit_proposal_review_status = 'REJECTED' edit_proposal.save() target = edit_proposal.edit_proposal_target push_notification( [ x for x in list( {edit_proposal.edit_proposal_by, target.created_by}) if x != request.user ], request.user, 'equipment-edit-proposal-rejected', { 'user': request.user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse('user_page', args=(request.user.username, ))), 'item': f'{target.brand.name if target.brand else _("(DIY)")} {target.name}', 'item_url': build_notification_url( AppRedirectionService.redirect( f'/equipment' f'/explorer' f'/{target.item_type}/{target.pk}' f'/{target.slug}')), 'edit_proposal_url': build_notification_url( AppRedirectionService.redirect( f'/equipment' f'/explorer' f'/{target.item_type}/{target.pk}' f'/{target.slug}' f'/edit-proposals' f'/{edit_proposal.pk}/')), 'comment': edit_proposal.edit_proposal_review_comment }) serializer = self.serializer_class(edit_proposal) return Response(serializer.data)
def reject(self, request, pk): if not request.user.groups.filter(name='equipment_moderators').exists(): raise PermissionDenied(request.user) strategy: GearMigrationStrategy = self.get_object() if strategy.migration_flag is None: return Response(status=409) if request.user == strategy.migration_flag_moderator: raise PermissionDenied target = strategy.migration_content_object push_notification( [strategy.migration_flag_moderator], request.user, 'equipment-item-migration-rejected', { 'user': request.user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse('user_page', args=(request.user.username,)) ), 'migration_flag': strategy.migration_flag, 'reason': request.data.get('reason'), 'comment': request.data.get('comment'), 'legacy_item': strategy.gear, 'target_item': f'{target.brand.name if target.brand else _("(DIY)")} {target.name}' if target else None, 'target_url': build_notification_url( AppRedirectionService.redirect( f'/equipment' f'/explorer' f'/{target.item_type}/{target.pk}' f'/{target.slug}' ) ) if target else None, 'migration_tool_url': build_notification_url( AppRedirectionService.redirect( f'/equipment' f'/migration-tool' ) ) if target else None, } ) strategy.gear.migration_flag_moderator_lock = None strategy.gear.migration_flag_moderator_lock_timestamp = None strategy.gear.save() strategy.delete() serializer = self.get_serializer(strategy) return Response(serializer.data)
def solution_post_save(sender, instance, created, **kwargs): ct = instance.content_type try: target = ct.get_object_for_this_type(pk=instance.object_id) except ct.model_class().DoesNotExist: return if ct.model == 'image': user = target.user elif ct.model == 'imagerevision': user = target.image.user else: return if instance.status == Solver.FAILED: notification = 'image_not_solved' elif instance.status == Solver.SUCCESS: notification = 'image_solved' else: return push_notification( [user], None, notification, { 'object_url': build_notification_url(settings.BASE_URL + target.get_absolute_url()) })
def nested_comment_post_save(sender, instance, created, **kwargs): if created: mentions = MentionsService.get_mentions(instance.text) CommentNotificationsService(instance).send_notifications() if hasattr(instance.content_object, "updated"): # This will trigger the auto_now fields in the content_object # We do it only if created, because the content_object needs to # only be updated if the number of comments changes. instance.content_object.save(keep_deleted=True) if instance.pending_moderation: CommentNotificationsService.send_moderation_required_email() else: mentions = cache.get( "user.%d.comment_pre_save_mentions" % instance.author.pk, []) for username in mentions: try: user = User.objects.get(username=username) push_notification( [user], instance.author, 'new_comment_mention', { 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.author), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.author}), }) except User.DoesNotExist: pass
def notify_mentioned(mentions): # type: (List[str]) -> None for username in mentions: user = get_object_or_None(User, username=username) if user is None: try: profile = get_object_or_None(UserProfile, real_name=username) if profile: user = profile.user except MultipleObjectsReturned: user = None if user: push_notification( [user], instance.user, 'new_forum_post_mention', { '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}), 'post': instance.topic.name, })
def post(self, request, *args, **kwargs): group = self.get_object() for pk in request.POST.getlist('users[]'): try: user = UserProfile.objects.get(user__pk=pk).user except UserProfile.DoesNotExist: continue group.invited_users.add(user) push_notification( [user], request.user, 'new_group_invitation', { 'inviter': request.user.userprofile.get_display_name(), 'inviter_page': reverse('user_page', args=(request.user.username,)), 'group_name': group.name, 'group_page': build_notification_url( settings.BASE_URL + reverse('group_detail', args=(group.pk, group.slug)), request.user), }) if request.is_ajax(): return self.render_json_response({ 'invited_users': [{ 'id': x.id, 'username': x.username, 'display_name': x.userprofile.get_display_name(), 'url': reverse('user_page', args=(x.username,)), 'revoke_url': reverse('group_revoke_invitation', args=(group.pk,)), } for x in group.invited_users.all()] }) return redirect(self.get_success_url())
def push_notification_for_group_join_request_rejection(group_pk, user_pk, moderator_pk): try: group = Group.objects.get(pk=group_pk) except Group.DoesNotExist: logger.warning('push_notification_for_group_join_request_rejection: group not found: %d' % group_pk) return try: user = User.objects.get(pk=user_pk) except User.DoesNotExist: logger.warning('push_notification_for_group_join_request_rejection: user not found: %d' % user_pk) return try: moderator = User.objects.get(pk=moderator_pk) except User.DoesNotExist: logger.warning('push_notification_for_group_join_request_rejection: moderator not found: %d' % moderator_pk) return push_notification( [user], moderator, 'group_join_request_rejected', { 'group_name': group.name, 'url': build_notification_url( settings.BASE_URL + reverse('group_detail', args=(group.pk,)), moderator ), })
def send_notifications(self, force=False): if self.comment.pending_moderation and not force: return instance = self.comment model_class = instance.content_type.model_class() obj = instance.content_type.get_object_for_this_type(id=instance.object_id) url = settings.BASE_URL + instance.get_absolute_url() if model_class == Image: if UserService(obj.user).shadow_bans(instance.author): log.info("Skipping notification for comment because %d shadow-bans %d" % ( obj.user.pk, instance.author.pk)) return if instance.parent and \ instance.parent.author != instance.author and \ not instance.pending_moderation: push_notification( [instance.parent.author], instance.author, 'new_comment_reply', { 'url': build_notification_url(url, instance.author), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse( 'user_page', kwargs={'username': instance.author.username}), } ) if instance.author != obj.user and \ (instance.parent is None or instance.parent.author != obj.user) and \ not instance.pending_moderation: push_notification( [obj.user], instance.author, 'new_comment', { 'url': build_notification_url(url, instance.author), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse( 'user_page', kwargs={'username': instance.author.username}), } ) if (force or not instance.pending_moderation) and not obj.is_wip: add_story(instance.author, verb='VERB_COMMENTED_IMAGE', action_object=instance, target=obj)
def send_approval_notification(self): if not self.comment.pending_moderation: push_notification( [self.comment.author], None, 'comment_approved', { 'url': build_notification_url(settings.BASE_URL + self.comment.get_absolute_url()) })
def reject(self, request, pk): model = self.get_serializer().Meta.model item: EquipmentItem = get_object_or_404(model.objects, pk=pk) if item.reviewed_by is not None and item.reviewer_decision == 'APPROVED': return Response("This item was already approved", HTTP_400_BAD_REQUEST) if item.created_by == request.user: return Response("You cannot review an item that you created", HTTP_400_BAD_REQUEST) item.reviewed_by = request.user item.reviewed_timestamp = timezone.now() item.reviewer_decision = 'REJECTED' item.reviewer_rejection_reason = request.data.get('reason') item.reviewer_comment = request.data.get('comment') if item.created_by: push_notification( [item.created_by], request.user, 'equipment-item-rejected', { 'user': request.user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse('user_page', args=(request.user.username, ))), 'item': f'{item.brand.name} {item.name}', 'reject_reason': item.reviewer_rejection_reason, 'comment': item.reviewer_comment, }) item.name = '[DELETED] %s' % item.name item.save() item.delete() Gear.objects.filter( migration_flag='MIGRATE', migration_content_type=ContentType.objects.get_for_model(model), migration_object_id=item.id, ).update( migration_flag=None, migration_content_type=None, migration_object_id=None, migration_flag_moderator=None, migration_flag_moderator_lock=None, migration_flag_moderator_lock_timestamp=None, migration_flag_reviewer=None, migration_flag_reviewer_decision='REJECTED_BAD_MIGRATION_TARGET', migration_flag_reviewer_rejection_comment=request.data.get( 'comment')) serializer = self.serializer_class(item) return Response(serializer.data)
def push_notification_for_new_image_revision(revision_pk): try: revision = ImageRevision.objects.get(pk=revision_pk) except ImageRevision.DoesNotExist: logger.error('push_notification_for_new_image called for revision not found: %d' % revision_pk) return if revision.skip_notifications or revision.image.is_wip: logger.error('push_notification_for_new_image called for revision of image that is wip: %d' % revision_pk) return followers = [x.user for x in ToggleProperty.objects.filter( property_type="follow", content_type=ContentType.objects.get_for_model(User), object_id=revision.image.user.pk)] if len(followers) > 0: previous_revision = ImageRevision.objects \ .filter(image=revision.image) \ .exclude(pk=revision.pk) \ .order_by('-uploaded').first() thumb = revision.thumbnail_raw('gallery', sync=True) push_notification(followers, revision.image.user, 'new_image_revision', { 'url': build_notification_url(settings.BASE_URL + revision.get_absolute_url(), revision.image.user), 'user_url': build_notification_url( settings.BASE_URL + revision.image.user.userprofile.get_absolute_url(), revision.image.user), 'user': revision.image.user.userprofile.get_display_name(), 'image_title': revision.image.title, 'title': revision.title, 'description': revision.description, 'previous_update_date': formats.date_format(max( revision.image.published, previous_revision.uploaded if previous_revision is not None else datetime.min ), "DATE_FORMAT"), 'image_thumbnail': thumb.url if thumb else None, }) else: logger.info( 'push_notification_for_new_image called for revision %d whose author has no followers' % revision_pk )
def send_moderation_required_notification(self): if self.comment.pending_moderation: ct = ContentType.objects.get_for_id(self.comment.content_type_id) if ct.model == 'image': image = self.comment.content_object push_notification([image.user], None, 'new_image_comment_moderation', { 'title': image.title, 'url': build_notification_url( '%s%s#c%d' % (settings.BASE_URL, image.get_absolute_url(), self.comment.pk), additional_query_args={'moderate-comment': 1}) })
def approve(self, request, pk): item = get_object_or_404(self.get_serializer().Meta.model.objects, pk=pk) if item.reviewed_by is not None: return Response("This item was already reviewed", HTTP_400_BAD_REQUEST) if item.created_by == request.user: return Response("You cannot review an item that you created", HTTP_400_BAD_REQUEST) item.reviewed_by = request.user item.reviewed_timestamp = timezone.now() item.reviewer_decision = 'APPROVED' item.reviewer_comment = request.data.get('comment') if item.created_by: push_notification( [item.created_by], request.user, 'equipment-item-approved', { 'user': request.user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse('user_page', args=(request.user.username, ))), 'item': f'{item.brand.name} {item.name}', 'item_url': build_notification_url( AppRedirectionService.redirect( f'/equipment/explorer/{EquipmentItemService(item).get_type()}/{item.pk}' )), 'comment': item.reviewer_comment, }) item.save() serializer = self.serializer_class(item) return Response(serializer.data)
def forum_topic_post_save(sender, instance, created, **kwargs): if created and hasattr(instance.forum, 'group'): group = instance.forum.group if instance.on_moderation: recipients = group.moderators.all() else: recipients = group.members.all() recipients = [x for x in recipients if x != instance.user] push_notification( recipients, instance.user, 'new_topic_in_group', { 'user_url': build_notification_url(settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user})), 'user': instance.user.userprofile.get_display_name(), 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'group_url': build_notification_url( settings.BASE_URL + reverse_url('group_detail', kwargs={'pk': group.pk}), instance.user), 'group_name': group.name, 'topic_title': instance.name, }, ) cache_key = make_template_fragment_key( 'home_page_latest_from_forums', (instance.user.pk, instance.user.userprofile.language)) cache.delete(cache_key)
def solution_pre_save(sender, instance, **kwargs): try: solution_before_save = Solution.objects.get(pk=instance.pk) except Solution.DoesNotExist: return if solution_before_save.status >= instance.status: return if instance.status == Solver.FAILED: notification = 'image_not_solved' elif instance.status == Solver.SUCCESS: notification = 'image_solved' elif instance.status == Solver.ADVANCED_SUCCESS: notification = 'image_solved_advanced' elif instance.status == Solver.ADVANCED_FAILED: notification = 'image_not_solved_advanced' else: return ct = instance.content_type try: target = ct.get_object_for_this_type(pk=instance.object_id) except ct.model_class().DoesNotExist: return if ct.model == 'image': user = target.user title = target.title thumb = target.thumbnail_raw('gallery', '0', sync=True) elif ct.model == 'imagerevision': user = target.image.user title = target.image.title thumb = target.image.thumbnail_raw('gallery', target.label, sync=True) else: return push_notification( [user], None, notification, { 'object_url': build_notification_url(settings.BASE_URL + target.get_absolute_url()), 'title': title, 'image_thumbnail': thumb.url if thumb else None, })
def nested_comment_post_save(sender, instance, created, **kwargs): if created: mentions = MentionsService.get_mentions(instance.text) if hasattr(instance.content_object, "updated"): # This will trigger the auto_now fields in the content_object # We do it only if created, because the content_object needs to # only be updated if the number of comments changes. save_kwargs = {} if issubclass(type(instance.content_object), SafeDeleteModel): save_kwargs['keep_deleted'] = True instance.content_object.save(**save_kwargs) if instance.pending_moderation: CommentNotificationsService( instance).send_moderation_required_notification() else: CommentNotificationsService(instance).send_notifications() else: mentions = cache.get( "user.%d.comment_pre_save_mentions" % instance.author.pk, []) if not instance.pending_moderation: 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: push_notification( [user], instance.author, 'new_comment_mention', { 'url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.author), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.author}), })
def handle(self, *args, **options): for user in User.objects.all(): number = 0 qs = Image.objects.filter(user=user, is_wip=False) number += qs.filter( (Q(subject_type=SubjectType.DEEP_SKY) & Q(subjects=None)) | (Q(subject_type=SubjectType.SOLAR_SYSTEM) & Q(solar_system_main_subject=None))).count() number += qs.filter( Q(imaging_telescopes=None) | Q(imaging_cameras=None)).count() number += qs.filter(Q(acquisition=None)).count() if number > 0: push_notification( [user], None, 'lacking_data_reminder', { 'number': number, 'url': build_notification_url(user.get_absolute_url() + '?public&sub=nodata') })
def post(self, request, *args, **kwargs): group = self.get_object() def doAdd(user, group): group.members.add(user) group.invited_users.remove(user) group.join_requests.remove(user) messages.success(request, _("You have joined the group")) if request.user in group.members.all(): messages.error(request, _("You already were a member of this group")) return redirect(self.get_success_url()) if group.public: if group.moderated and request.user != group.owner: group.join_requests.add(request.user) messages.warning(request, _("This is a moderated group, and your join request will be reviewed by a moderator")) push_notification( group.moderators.all(), request.user, 'new_group_join_request', { 'requester': request.user.userprofile.get_display_name(), 'group_name': group.name, 'url': build_notification_url( settings.BASE_URL + reverse('group_moderate_join_requests', args=(group.pk,)), request.user) }) return redirect(self.get_success_url()) else: doAdd(request.user, group) return redirect(self.get_success_url()) else: if request.user in group.invited_users.all() or request.user == group.owner: doAdd(request.user, group) return redirect(self.get_success_url()) return HttpResponseForbidden()
def push_notification_for_new_image_revision(revision_pk): try: revision = ImageRevision.objects.get(pk=revision_pk) except ImageRevision.DoesNotExist: logger.error( 'push_notification_for_new_image called for revision not found: %d' % revision_pk) return if revision.skip_notifications or revision.image.is_wip: logger.error( 'push_notification_for_new_image called for revision of image that is wip: %d' % revision_pk) return followers = [ x.user for x in ToggleProperty.objects.filter( property_type="follow", content_type=ContentType.objects.get_for_model(User), object_id=revision.image.user.pk) ] if len(followers) > 0: push_notification( followers, revision.image.user, 'new_image_revision', { 'object_url': build_notification_url( settings.BASE_URL + revision.get_absolute_url(), revision.image.user), 'originator': revision.image.user.userprofile.get_display_name(), }) else: logger.error( 'push_notification_for_new_image called for revision %d whose author has no followers' % revision_pk)
def reject(self, request, pk): from astrobin_apps_equipment.models import Sensor from astrobin_apps_equipment.models import Camera from astrobin_apps_equipment.models import CameraEditProposal from astrobin_apps_equipment.models import Telescope from astrobin_apps_equipment.models import Mount from astrobin_apps_equipment.models import Filter from astrobin_apps_equipment.models import Accessory from astrobin_apps_equipment.models import Software model = self.get_serializer().Meta.model item: EquipmentItem = get_object_or_404(model.objects, pk=pk) if item.reviewed_by is not None and item.reviewer_decision == 'APPROVED': return Response("This item was already approved", HTTP_400_BAD_REQUEST) if item.created_by == request.user: return Response("You cannot review an item that you created", HTTP_400_BAD_REQUEST) item.reviewed_by = request.user item.reviewed_timestamp = timezone.now() item.reviewer_decision = 'REJECTED' item.reviewer_rejection_reason = request.data.get('reason') item.reviewer_comment = request.data.get('comment') if item.created_by and item.created_by != request.user: push_notification( [item.created_by], request.user, 'equipment-item-rejected', { 'user': request.user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse('user_page', args=(request.user.username, ))), 'item': f'{item.brand.name if item.brand else _("(DIY)")} {item.name}', 'reject_reason': item.reviewer_rejection_reason, 'comment': item.reviewer_comment, }) if item.klass == EquipmentItemKlass.SENSOR: Camera.all_objects.filter(sensor=item).update(sensor=None) CameraEditProposal.all_objects.filter(sensor=item).update( sensor=None) item.delete() GearMigrationStrategy.objects.filter( migration_flag='MIGRATE', migration_content_type=ContentType.objects.get_for_model(model), migration_object_id=item.id, ).delete() if item.brand: brand_has_items = False for klass in (Sensor, Camera, Telescope, Mount, Filter, Accessory, Software): if klass.objects.filter(brand=item.brand).exists(): brand_has_items = True break if not brand_has_items: item.brand.delete() serializer = self.serializer_class(item) return Response(serializer.data)
def send_notifications(self, force=False): if self.comment.pending_moderation and not force: return instance = self.comment model_class = instance.content_type.model_class() obj = instance.content_type.get_object_for_this_type(id=instance.object_id) object_owner = None notification = None mentions = MentionsService.get_mentions(instance.text) url = None if model_class == Image: object_owner = obj.user notification = 'new_comment' url = settings.BASE_URL + instance.get_absolute_url() elif hasattr(model_class, 'edit_proposal_by'): object_owner = obj.edit_proposal_by notification = 'new_comment_to_edit_proposal' url = instance.get_absolute_url() elif model_class == Iotd: object_owner = obj.judge notification = 'new_comment_to_scheduled_iotd' url = AppRedirectionService.redirect(f'/iotd/judgement-queue#comments-{obj.pk}-{instance.pk}') if UserService(object_owner).shadow_bans(instance.author): log.info("Skipping notification for comment because %d shadow-bans %d" % ( object_owner.pk, instance.author.pk)) return exclude = MentionsService.get_mentioned_users_with_notification_enabled(mentions, 'new_comment_mention') if instance.parent and \ instance.parent.author != instance.author and \ not instance.pending_moderation: recipients = [x for x in [instance.parent.author] if x not in exclude] if recipients: push_notification( recipients, instance.author, 'new_comment_reply', { 'url': build_notification_url(url, instance.author), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse( 'user_page', kwargs={'username': instance.author.username} ), } ) if model_class == Image: if (force or not instance.pending_moderation) and not obj.is_wip: add_story(instance.author, verb='VERB_COMMENTED_IMAGE', action_object=instance, target=obj) if object_owner and notification: if instance.author != object_owner and \ (instance.parent is None or instance.parent.author != object_owner) and \ not instance.pending_moderation: recipients = [x for x in [object_owner] if x not in exclude] if recipients: push_notification( recipients, instance.author, notification, { 'url': build_notification_url(url, instance.author), 'user': instance.author.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse( 'user_page', kwargs={'username': instance.author.username} ), } )
def send_edit_proposal_created_notification(sender, instance, created, **kwargs): if created and instance.edit_proposal_target.created_by: target = instance.edit_proposal_target owner = instance.edit_proposal_target.created_by user = instance.edit_proposal_by recipients = [] if owner != user: recipients.append(owner) previous_proposals = User.objects.filter( **{ f'astrobin_apps_equipment_{instance.__class__.__name__.lower()}_edit_proposals__' f'edit_proposal_target': target }) previous_proposals_reviewed = User.objects.filter( **{ f'astrobin_apps_equipment_{instance.__class__.__name__.lower()}_edit_proposals_reviewed__' f'edit_proposal_target': target }) commenters = User.objects.filter(pk__in=NestedComment.objects.filter( content_type=ContentType.objects.get_for_model(instance.__class__), object_id__in=instance.__class__.objects.filter( edit_proposal_target=target)).values_list('author', flat=True)) recipients.extend(list(previous_proposals)) recipients.extend(list(previous_proposals_reviewed)) recipients.extend(list(commenters)) recipients = list(set(recipients)) recipients.remove(user) if len(recipients) > 0: push_notification( recipients, user, 'equipment-edit-proposal-created', { 'user': user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse('user_page', args=(user.username, ))), 'item': f'{target.brand.name if target.brand else _("(DIY)")} {target.name}', 'item_url': build_notification_url( AppRedirectionService.redirect( f'/equipment' f'/explorer' f'/{target.item_type}/{target.pk}' f'/{target.slug}')), 'edit_proposal_url': build_notification_url( AppRedirectionService.redirect( f'/equipment' f'/explorer' f'/{target.item_type}/{target.pk}' f'/{target.slug}' f'/edit-proposals' f'/{instance.pk}/')), })
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 forum_post_post_save(sender, instance, created, **kwargs): def notify_subscribers(): push_notification( list(instance.topic.subscribers.exclude(pk=instance.user.pk)), instance.user, 'new_forum_reply', { 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url('user_page', kwargs={'username': instance.user}), 'post_url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'topic_url': build_notification_url( settings.BASE_URL + instance.topic.get_absolute_url(), instance.user), 'topic_name': instance.topic.name, 'unsubscribe_url': build_notification_url( settings.BASE_URL + reverse_url('pybb:delete_subscription', args=[instance.topic.id]), instance.user) }) if created: mentions = MentionsService.get_mentions(instance.body) if hasattr(instance.topic.forum, 'group'): instance.topic.forum.group.save() # trigger date_updated update if get_pybb_profile(instance.user).autosubscribe and \ perms.may_subscribe_topic(instance.user, instance.topic): instance.topic.subscribers.add(instance.user) if not instance.on_moderation: notify_subscribers() else: NotificationsService.email_superusers( 'New forum post needs moderation', '%s%s' % (settings.BASE_URL, instance.get_absolute_url())) else: mentions = cache.get( "user.%d.forum_post_pre_save_mentions" % instance.user.pk, []) if cache.get("user.%d.forum_post_pre_save_approved" % instance.user.pk): notify_subscribers() for username in mentions: try: user = User.objects.get(username=username) push_notification( [user], instance.user, 'new_forum_post_mention', { '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}), 'post': instance.topic.name, }) except User.DoesNotExist: pass cache_key = make_template_fragment_key( 'home_page_latest_from_forums', (instance.user.pk, instance.user.userprofile.language)) cache.delete(cache_key)
def forum_post_post_save(sender, instance, created, **kwargs): def notify_subscribers(mentions): # type: (List[str]) -> None recipients = list( instance.topic.subscribers.exclude(pk__in=list( set([instance.user.pk] + [ x.pk for x in MentionsService. get_mentioned_users_with_notification_enabled( mentions, 'new_forum_post_mention') ])))) if recipients: push_notification( recipients, instance.user, 'new_forum_reply', { 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user}), 'post_url': build_notification_url( settings.BASE_URL + instance.get_absolute_url(), instance.user), 'topic_url': build_notification_url( settings.BASE_URL + instance.topic.get_absolute_url(), instance.user), 'topic_name': instance.topic.name, 'unsubscribe_url': build_notification_url( settings.BASE_URL + reverse_url('pybb:delete_subscription', args=[instance.topic.id]), instance.user) }) def notify_mentioned(mentions): # type: (List[str]) -> None for username in mentions: user = get_object_or_None(User, username=username) if user is None: try: profile = get_object_or_None(UserProfile, real_name=username) if profile: user = profile.user except MultipleObjectsReturned: user = None if user: push_notification( [user], instance.user, 'new_forum_post_mention', { '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}), 'post': instance.topic.name, }) if created: if hasattr(instance.topic.forum, 'group'): instance.topic.forum.group.save() # trigger date_updated update if get_pybb_profile(instance.user).autosubscribe and \ perms.may_subscribe_topic(instance.user, instance.topic): instance.topic.subscribers.add(instance.user) mentions = MentionsService.get_mentions(instance.body) if not instance.on_moderation: notify_subscribers(mentions) notify_mentioned(mentions) else: NotificationsService.email_superusers( 'New forum post needs moderation', '%s%s' % (settings.BASE_URL, instance.get_absolute_url())) else: mentions = cache.get( "post.%d.forum_post_pre_save_mentions" % instance.pk, []) cache.delete("post.%d.forum_post_pre_save_mentions" % instance.pk) if cache.get("post.%d.forum_post_pre_save_approved" % instance.pk): push_notification( [instance.user], None, 'forum_post_approved', { 'url': build_notification_url(settings.BASE_URL + instance.get_absolute_url()) }) notify_subscribers(mentions) notify_mentioned(mentions) cache.delete("post.%d.forum_post_pre_save_approved" % instance.pk) cache_key = make_template_fragment_key( 'home_page_latest_from_forums', (instance.user.pk, instance.user.userprofile.language)) cache.delete(cache_key)
def group_members_changed(sender, instance, **kwargs): action = kwargs['action'] pk_set = kwargs['pk_set'] group_sync_map = { 'IOTD Submitters': ['iotd_submitters', 'content_moderators', 'iotd_staff'], 'IOTD Reviewers': ['iotd_reviewers', 'content_moderators', 'iotd_staff'], 'IOTD Judges': ['iotd_judges', 'content_moderators', 'iotd_staff'], } if instance.name in list(group_sync_map.keys()): for django_group in group_sync_map[instance.name]: DjangoGroup.objects.get_or_create(name=django_group) django_groups = DjangoGroup.objects.filter( name__in=group_sync_map[instance.name]) try: iotd_staff_group = Group.objects.get(name='IOTD Staff') except Group.DoesNotExist: iotd_staff_group = None if action == 'post_add': users = [ profile.user for profile in UserProfile.objects.filter(user__pk__in=pk_set) ] instance.save() # trigger date_updated update if instance.public: for pk in pk_set: user = UserProfile.objects.get(user__pk=pk).user if user != instance.owner: followers = [ x.user for x in ToggleProperty.objects. toggleproperties_for_object("follow", user) ] push_notification( followers + [instance.owner], user, 'user_joined_public_group', { 'user': user.userprofile.get_display_name(), 'user_url': build_notification_url( settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': user.username}), user), 'group_name': instance.name, 'url': build_notification_url( settings.BASE_URL + reverse_url( 'group_detail', args=(instance.pk, )), user), }) add_story(user, verb='VERB_JOINED_GROUP', action_object=instance) if instance.autosubmission: images = Image.objects_including_wip.filter(user__pk__in=pk_set) for image in images: instance.images.add(image) # Sync IOTD AstroBin groups with django groups if instance.name in list(group_sync_map.keys()): for django_group in django_groups: django_group.user_set.add(*list(users)) if iotd_staff_group: for user in users: iotd_staff_group.members.add(user) elif action == 'post_remove': users = [ profile.user for profile in UserProfile.objects.filter(user__pk__in=pk_set) ] images = Image.objects_including_wip.filter(user__pk__in=pk_set) for image in images: instance.images.remove(image) if instance.forum and not instance.public: topics = Topic.objects.filter(forum=instance.forum) for topic in topics: topic.subscribers.remove(*User.objects.filter( pk__in=kwargs['pk_set'])) # Sync IOTD AstroBin groups with django groups if instance.name in list(group_sync_map.keys()): all_members = [] all_members_chain = chain([ x.members.all() for x in Group.objects \ .filter(name__in=list(group_sync_map.keys())) \ .exclude(name=instance.name) ]) for chain_item in all_members_chain: all_members += chain_item for user in [x for x in users if x not in all_members]: for django_group in django_groups: django_group.user_set.remove(user) if iotd_staff_group: iotd_staff_group.members.remove(user) elif action == 'pre_clear': # Sync IOTD AstroBin groups with django groups users = instance.members.all() if instance.name in list(group_sync_map.keys()): all_members = [] all_members_chain = chain([ x.members.all() for x in Group.objects \ .filter(name__in=list(group_sync_map.keys())) \ .exclude(name=instance.name) ]) for chain_item in all_members_chain: all_members += chain_item for user in [x for x in users if x not in all_members]: for django_group in django_groups: django_group.user_set.remove(user) if iotd_staff_group: iotd_staff_group.members.remove(user) elif action == 'post_clear': instance.images.clear()
def toggleproperty_post_save(sender, instance, created, **kwargs): if hasattr(instance.content_object, "updated"): # This will trigger the auto_now fields in the content_object kwargs = {} if issubclass(type(instance.content_object), SafeDeleteModel): kwargs['keep_deleted'] = True instance.content_object.save(**kwargs) if created: verb = None if instance.property_type in ("like", "bookmark"): if instance.content_type == ContentType.objects.get_for_model( Image): image = instance.content_type.get_object_for_this_type( id=instance.object_id) Image.all_objects.filter(pk=instance.content_object.pk).update( updated=timezone.now()) if image.is_wip: return if instance.property_type == "like": verb = 'VERB_LIKED_IMAGE' elif instance.property_type == "bookmark": verb = 'VERB_BOOKMARKED_IMAGE' else: return push_notification( [instance.content_object.user], instance.user, 'new_' + instance.property_type, { 'url': build_notification_url( settings.BASE_URL + instance.content_object.get_absolute_url(), instance.user), 'title': instance.content_object.title, 'user': instance.user.userprofile.get_display_name(), 'user_url': settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user.username}), }) elif instance.content_type == ContentType.objects.get_for_model( NestedComment): push_notification( [instance.content_object.author], instance.user, 'new_comment_like', { 'url': build_notification_url( settings.BASE_URL + instance.content_object.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.username}), 'comment': instance.content_object.text }) UserProfile.all_objects.filter( user=instance.content_object.author).update( updated=timezone.now()) elif instance.content_type == ContentType.objects.get_for_model( Post): push_notification( [instance.content_object.user], instance.user, 'new_forum_post_like', { 'url': build_notification_url( settings.BASE_URL + instance.content_object.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.username}), 'post': instance.content_object.topic.name }) UserProfile.all_objects.filter( user=instance.content_object.user).update( updated=timezone.now()) if verb is not None: add_story(instance.user, verb=verb, action_object=instance.content_object) elif instance.property_type == "follow": user_ct = ContentType.objects.get_for_model(User) if instance.content_type == user_ct: followed_user = user_ct.get_object_for_this_type( pk=instance.object_id) push_notification( [followed_user], instance.user, 'new_follower', { 'object': instance.user.userprofile.get_display_name(), 'object_url': build_notification_url( settings.BASE_URL + reverse_url( 'user_page', kwargs={'username': instance.user.username}), instance.user), })