コード例 #1
0
    def post(self, request):
        ids = request.POST.getlist('ids[]')
        Image.objects_including_wip.filter(pk__in=ids).update(
            moderator_decision=1,
            moderated_when=datetime.date.today(),
            moderated_by=request.user)

        for image in Image.objects_including_wip.filter(pk__in=ids):
            if not image.is_wip:
                followers = [
                    x.user for x in ToggleProperty.objects.filter(
                        property_type="follow",
                        content_type=ContentType.objects.get_for_model(User),
                        object_id=image.user.pk)
                ]

                thumb = image.thumbnail_raw('gallery', None, sync=True)
                push_notification(
                    followers, image.user, 'new_image', {
                        'image': image,
                        'image_thumbnail': thumb.url if thumb else None
                    })

                add_story(image.user,
                          verb='VERB_UPLOADED_IMAGE',
                          action_object=image)

        return self.render_json_response({
            'status': 'OK',
        })
コード例 #2
0
ファイル: group_invite.py プロジェクト: sayitfast/astrobin
    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], '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': settings.BASE_URL + reverse('group_detail', args=(group.pk,)),
                              })

        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())
コード例 #3
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
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], notification,
        {'object_url': settings.BASE_URL + target.get_absolute_url()})
コード例 #4
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def subscription_paid(sender, **kwargs):
    subscription = kwargs.get('subscription')
    user = kwargs.get('user')
    profile = user.userprofile

    UserProfile.all_objects.filter(user=user).update(updated=timezone.now())
    PremiumService.clear_subscription_status_cache_keys(user.pk)

    if subscription.group.name == 'astrobin_lite':
        profile.premium_counter = 0
        profile.save(keep_deleted=True)
    elif subscription.group.name == 'astrobin_lite_2020':
        profile.premium_counter = Image.objects_including_wip.filter(
            user=user).count()
        profile.save(keep_deleted=True)

    if 'premium' in subscription.category and Transaction.objects.filter(
            user=user,
            event='new usersubscription',
            timestamp__gte=DateTimeService.now() -
            datetime.timedelta(minutes=5)):
        push_notification([user], None, 'new_subscription',
                          {'BASE_URL': settings.BASE_URL})
    else:
        push_notification([user], None, 'new_payment',
                          {'BASE_URL': settings.BASE_URL})
コード例 #5
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
def subscription_subscribed(sender, **kwargs):
    subscription = kwargs.get("subscription")
    usersubscription = kwargs.get("usersubscription")

    if subscription.group.name in [
            'astrobin_lite', 'astrobin_premium', 'astrobin_lite_2020',
            'astrobin_premium_2020', 'astrobin_ultimate_2020'
    ] and subscription.recurrence_unit is None:
        # AstroBin Premium/Lite/Ultimate are valid for 1 year
        usersubscription.expires = datetime.datetime.now()
        usersubscription.extend(datetime.timedelta(days=365.2425))
        usersubscription.save()

        # Invalidate other premium subscriptions
        UserSubscription.active_objects \
            .filter(user=usersubscription.user,
                    subscription__category__startswith='premium') \
            .exclude(pk=usersubscription.pk) \
            .update(active=False)

    if subscription.group.name == 'astrobin_lite':
        user = kwargs.get("user")
        profile = user.userprofile
        profile.premium_counter = 0
        profile.save(keep_deleted=True)

    if subscription.category == 'premium':
        push_notification([usersubscription.user], 'new_subscription',
                          {'BASE_URL': settings.BASE_URL})
コード例 #6
0
    def post(self, request, *args, **kwargs):
        if request.is_ajax():
            group = self.get_object()
            user = UserProfile.objects.get(
                user__pk=self.request.POST.get('user')).user

            if user not in group.join_requests.all():
                return HttpResponseForbidden()

            group.join_requests.remove(user)
            push_notification(
                [user], 'group_join_request_rejected', {
                    'group_name':
                    group.name,
                    'url':
                    settings.BASE_URL +
                    reverse('group_detail', args=(group.pk, )),
                })

            return self.render_json_response({
                'member': user.pk,
            })

        # Only AJAX allowed
        return HttpResponseForbidden()
コード例 #7
0
ファイル: image.py プロジェクト: astrobin/astrobin
    def post(self, request, *args, **kwargs):
        image = self.get_object()
        if image.is_wip:
            previously_published = image.published
            image.is_wip = False
            image.save()

            if not previously_published:
                followers = [
                    x.user for x in
                    ToggleProperty.objects.toggleproperties_for_object(
                        "follow",
                        UserProfile.objects.get(user__pk = request.user.pk).user)
                ]
                push_notification(followers, 'new_image',
                    {
                        'originator': request.user.userprofile.get_display_name(),
                        'object_url': settings.BASE_URL + image.get_absolute_url()
                    })

                add_story(image.user, verb = 'VERB_UPLOADED_IMAGE', action_object = image)

            messages.success(request, _("Image moved to the public area."))

        return super(ImagePromoteView, self).post(request, args, kwargs)
コード例 #8
0
ファイル: signals.py プロジェクト: sayitfast/astrobin
def subscription_signed_up(sender, **kwargs):
    subscription = kwargs.get('subscription')
    user_subscription = kwargs.get('usersubscription')
    user = kwargs.get('user')

    if 'premium' in subscription.category:
        if user_subscription.expires is None:
            user_subscription.expires = DateTimeService.today()
        user_subscription.extend(datetime.timedelta(days=365.2425))
        user_subscription.save()

        # Invalidate other premium subscriptions
        UserSubscription.active_objects \
            .filter(user=user_subscription.user,
                    subscription__category__startswith='premium') \
            .exclude(pk=user_subscription.pk) \
            .update(active=False)

        if Transaction.objects.filter(user=user,
                                      event='new usersubscription',
                                      timestamp__gte=DateTimeService.now() -
                                      datetime.timedelta(minutes=5)):
            push_notification([user], 'new_subscription',
                              {'BASE_URL': settings.BASE_URL})
        else:
            push_notification([user], 'new_payment',
                              {'BASE_URL': settings.BASE_URL})
コード例 #9
0
ファイル: tasks.py プロジェクト: siovene/astrobin
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
            ),
        })
コード例 #10
0
ファイル: image.py プロジェクト: rkaczorek/astrobin
    def post(self, request, *args, **kwargs):
        image = self.get_object()
        if image.is_wip:
            previously_published = image.published
            image.is_wip = False
            image.save(keep_deleted=True)

            if not previously_published:
                followers = [
                    x.user for x in
                    ToggleProperty.objects.toggleproperties_for_object(
                        "follow",
                        UserProfile.objects.get(user__pk=request.user.pk).user)
                ]
                push_notification(
                    followers, 'new_image', {
                        'originator':
                        request.user.userprofile.get_display_name(),
                        'object_url':
                        settings.BASE_URL + image.get_absolute_url()
                    })

                add_story(image.user,
                          verb='VERB_UPLOADED_IMAGE',
                          action_object=image)

            messages.success(request, _("Image moved to the public area."))

        return super(ImagePromoteView, self).post(request, args, kwargs)
コード例 #11
0
    def post(self, request, *args, **kwargs):
        image = self.get_object()
        if image.is_wip:
            skip_notifications = request.POST.get('skip_notifications',
                                                  'off').lower() == 'on'
            previously_published = image.published
            image.is_wip = False
            image.save(keep_deleted=True)

            if not previously_published and not skip_notifications:
                followers = [
                    x.user for x in
                    ToggleProperty.objects.toggleproperties_for_object(
                        "follow",
                        UserProfile.objects.get(user__pk=request.user.pk).user)
                ]

                thumb = image.thumbnail_raw('gallery', {'sync': True})
                push_notification(
                    followers, 'new_image', {
                        'image': image,
                        'image_thumbnail': thumb.url if thumb else None
                    })

                add_story(image.user,
                          verb='VERB_UPLOADED_IMAGE',
                          action_object=image)

            messages.success(request, _("Image moved to the public area."))

        return super(ImagePromoteView, self).post(request, args, kwargs)
コード例 #12
0
ファイル: views.py プロジェクト: astrobin/astrobin
    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(), 'new_group_join_request',
                    {
                        'requester': request.user.userprofile.get_display_name(),
                        'group_name': group.name,
                        'url': settings.BASE_URL + reverse('group_moderate_join_requests', args = (group.pk,)),
                    })
                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()
コード例 #13
0
def user_created(sender, user, request, **kwargs):
    form = AstroBinRegistrationForm(request.POST)
    profile, created = UserProfile.objects.get_or_create(user=user)
    changed = False

    if 'referral_code' in form.data and form.data['referral_code'] != '':
        profile.referral_code = form.data['referral_code']
        changed = True

    if 'tos' in form.data:
        profile.accept_tos = form.data['tos'] == "on"
        changed = True

    if 'important_communications' in form.data:
        profile.receive_important_communications = form.data[
            'important_communications'] == "on"
        changed = True

    if 'newsletter' in form.data:
        profile.receive_newsletter = form.data['newsletter'] == "on"
        changed = True

    if 'marketing_material' in form.data:
        profile.receive_marketing_and_commercial_material = form.data[
            'marketing_material'] == "on"
        changed = True

    if changed:
        profile.save(keep_deleted=True)

    push_notification([user], None, 'welcome_to_astrobin', {
        'BASE_URL': settings.BASE_URL,
    })
コード例 #14
0
ファイル: views.py プロジェクト: astrobin/astrobin
    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], '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': settings.BASE_URL + reverse('group_detail', args = (group.pk,)),
                })

        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())
コード例 #15
0
def push_notification_for_new_image(user_pk, image_pk):
    try:
        image = Image.objects_including_wip.get(pk=image_pk)
    except Image.DoesNotExist:
        logger.error('push_notification_for_new_image called for image not found: %d' % image_pk)
        return

    if image.is_wip:
        logger.error('push_notification_for_new_image called for image that is wip: %d' % image_pk)
        return

    followers = [
        x.user for x in
        ToggleProperty.objects.toggleproperties_for_object(
            "follow",
            UserProfile.objects.get(user__pk=user_pk).user)
    ]

    if len(followers) > 0:
        thumb = image.thumbnail_raw('gallery', None, sync=True)
        push_notification(followers, image.user, 'new_image', {
            'image': image,
            'image_thumbnail': thumb.url if thumb else None
        })
    else:
        logger.info('push_notification_for_new_image called for image %d whose author %d has no followers' % (
            image_pk, user_pk)
        )
コード例 #16
0
def rawdata_publicdatapool_image_added(sender, instance, action, reverse,
                                       model, pk_set, **kwargs):
    if action == 'post_add' and len(pk_set) > 0:
        contributors = [i.user for i in instance.images.all()]
        users = [instance.creator] + contributors
        image = Image.objects.get(pk=list(pk_set)[0])
        submitter = image.user
        users[:] = [x for x in users if x != submitter]
        push_notification(
            users,
            'rawdata_posted_image_to_public_pool',
            {
                'user_name':
                submitter.userprofile.get_display_name(),
                'user_url':
                reverse_url('user_page',
                            kwargs={'username': submitter.username}),
                'pool_name':
                instance.name,
                'pool_url':
                reverse_url('rawdata.publicdatapool_detail',
                            kwargs={'pk': instance.pk}),
            },
        )

        add_story(submitter,
                  verb='VERB_ADDED_IMAGE_TO_DATA_POOL',
                  action_object=image,
                  target=instance)
コード例 #17
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
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)
    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], 'new_comment_mention', {
                    'url':
                    settings.BASE_URL + instance.get_absolute_url(),
                    'user':
                    instance.author.userprofile.get_display_name(),
                    'user_url':
                    settings.BASE_URL + reverse_url(
                        'user_page', kwargs={'username': instance.author}),
                })
        except User.DoesNotExist:
            pass
コード例 #18
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
def forum_post_post_save(sender, instance, created, **kwargs):
    if created:
        mentions = MentionsService.get_mentions(instance.body)
        if hasattr(instance.topic.forum, 'group'):
            instance.topic.forum.group.save()  # trigger date_updated update
    else:
        mentions = cache.get(
            "user.%d.forum_post_pre_save_mentions" % instance.user.pk, [])

    for username in mentions:
        try:
            user = User.objects.get(username=username)
            push_notification(
                [user], 'new_forum_post_mention', {
                    'url':
                    settings.BASE_URL + instance.get_absolute_url(),
                    '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
    def handle(self, *args, **kwargs):
        user_subscriptions = UserSubscription.objects\
            .filter(
                subscription__name__in = [
                    "AstroBin Lite (autorenew)",
                    "AstroBin Premium (autorenew)",
                ],
                cancelled=False,
                expires = datetime.now() + timedelta(days = 7))\
            .exclude(subscription__recurrence_unit = None)

        for user_subscription in user_subscriptions:
            push_notification([user_subscription.user],
                              'expiring_subscription_autorenew', {
                                  'user_subscription': user_subscription,
                              })

        user_subscriptions = UserSubscription.objects \
            .filter(
            subscription__name__in=[
                "AstroBin Lite (autorenew)",
                "AstroBin Premium (autorenew)",
            ],
            cancelled=False,
            expires=datetime.now() + timedelta(days=30)) \
            .exclude(subscription__recurrence_unit=None)

        for user_subscription in user_subscriptions:
            push_notification([user_subscription.user],
                              'expiring_subscription_autorenew_30d', {
                                  'user_subscription': user_subscription,
                              })
コード例 #20
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
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,
            'new_topic_in_group',
            {
                'user':
                instance.user.userprofile.get_display_name(),
                'url':
                settings.BASE_URL + instance.get_absolute_url(),
                'group_url':
                settings.BASE_URL +
                reverse_url('group_detail', kwargs={'pk': group.pk}),
                'group_name':
                group.name,
                'topic_title':
                instance.name,
            },
        )
コード例 #21
0
def send_never_activated_account_reminder():
    users = never_activated_accounts()

    for user in users:
        if not hasattr(user, 'userprofile'):
            user.delete()
            continue

        push_notification(
            [user], None, 'never_activated_account', {
                'date':
                user.date_joined,
                'username':
                user.username,
                'activation_link':
                '%s/%s' % (
                    settings.BASE_URL,
                    reverse(
                        'registration_activate',
                        args=(RegistrationView().get_activation_key(user), )),
                )
            })

        user.userprofile.never_activated_account_reminder_sent = timezone.now()
        user.userprofile.save(keep_deleted=True)

        logger.debug("Sent 'never activated account reminder' to %d" % user.pk)
コード例 #22
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def solution_post_save(sender, instance, created, **kwargs):
    notification = None
    user = None

    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], notification,
        {'object_url': settings.BASE_URL + target.get_absolute_url()})
コード例 #23
0
ファイル: moderation.py プロジェクト: jensrick/astrobin
    def post(self, request):
        ids = request.POST.getlist('ids[]')
        Image.objects_including_wip.filter(pk__in=ids).update(
            moderator_decision=1,
            moderated_when=datetime.date.today(),
            moderated_by=request.user)

        for image in Image.objects_including_wip.filter(pk__in=ids):
            if not image.is_wip:
                followers = [
                    x.user for x in ToggleProperty.objects.filter(
                        property_type="follow",
                        content_type=ContentType.objects.get_for_model(User),
                        object_id=image.user.pk)
                ]

                push_notification(
                    followers, 'new_image', {
                        'object_url':
                        settings.BASE_URL + image.get_absolute_url(),
                        'originator':
                        image.user.userprofile.get_display_name(),
                    })

                add_story(image.user,
                          verb='VERB_UPLOADED_IMAGE',
                          action_object=image)

        return self.render_json_response({
            'status': 'OK',
        })
コード例 #24
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
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],
                'new_topic_in_group',
                {
                    'user':
                    instance.user.userprofile.get_display_name(),
                    'url':
                    settings.BASE_URL + instance.get_absolute_url(),
                    'group_url':
                    reverse_url('group_detail', kwargs={'pk': group.pk}),
                    'group_name':
                    group.name,
                    'topic_title':
                    instance.name,
                },
            )
コード例 #25
0
 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)
         })
コード例 #26
0
ファイル: signals.py プロジェクト: HunterHarling/astrobin
def group_post_save(sender, instance, created, **kwargs):
    if created and instance.creator is not None:
        instance.members.add(instance.creator)
        if instance.moderated:
            instance.moderators.add(instance.creator)

        if instance.public:
            followers = [
                x.user
                for x in ToggleProperty.objects.toggleproperties_for_object(
                    "follow",
                    UserProfile.objects.get(user__pk=instance.creator.pk).user)
            ]
            push_notification(
                followers, 'new_public_group_created', {
                    'creator':
                    instance.creator.userprofile.get_display_name(),
                    'group_name':
                    instance.name,
                    'url':
                    settings.BASE_URL +
                    reverse_url('group_detail', args=(instance.pk, )),
                })

            add_story(instance.creator,
                      verb='VERB_CREATED_PUBLIC_GROUP',
                      action_object=instance)
コード例 #27
0
ファイル: signals.py プロジェクト: astrobin/astrobin
    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)
                })
コード例 #28
0
ファイル: signals.py プロジェクト: astrobin/astrobin
 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,
                 })
コード例 #29
0
 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())
             })
コード例 #30
0
    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)
コード例 #31
0
    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)
コード例 #32
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def top_pick_nominations_archive_post_save(sender, instance, created,
                                           **kwargs):
    if created:
        image = instance.image
        thumb = image.thumbnail_raw('gallery', None, sync=True)

        push_notification([image.user], None, 'your_image_is_tpn', {
            'image': image,
            'image_thumbnail': thumb.url if thumb else None
        })
コード例 #33
0
ファイル: signals.py プロジェクト: jensrick/astrobin
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
        instance.content_object.save(keep_deleted=True)

    if created:
        if instance.property_type in ("like", "bookmark"):
            if instance.property_type == "like":
                verb = 'VERB_LIKED_IMAGE'
            elif instance.property_type == "bookmark":
                verb = 'VERB_BOOKMARKED_IMAGE'

            if instance.content_type == ContentType.objects.get_for_model(
                    Image):
                image = instance.content_type.get_object_for_this_type(
                    id=instance.object_id)
                if image.is_wip:
                    return

            add_story(instance.user,
                      verb=verb,
                      action_object=instance.content_object)

            if instance.content_type == ContentType.objects.get_for_model(
                    Image):
                push_notification(
                    [instance.content_object.user],
                    'new_' + instance.property_type, {
                        'url':
                        settings.BASE_URL +
                        instance.content_object.get_absolute_url(),
                        '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.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], 'new_follower', {
                        'object':
                        instance.user.userprofile.get_display_name(),
                        'object_url':
                        settings.BASE_URL + reverse_url(
                            'user_page',
                            kwargs={'username': instance.user.username}),
                    })
コード例 #34
0
ファイル: signals.py プロジェクト: rkaczorek/astrobin
def rawdata_privatesharedfolder_user_added(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == 'post_add' and len(pk_set) > 0:
        user = UserProfile.objects.get(user__pk=list(pk_set)[0]).user
        push_notification(
            [user],
            'rawdata_invited_to_private_folder',
            {
                'folder_name': instance.name,
                'folder_url': reverse_url('rawdata.privatesharedfolder_detail', kwargs={'pk': instance.pk}),
            },
        )
コード例 #35
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def rawdata_privatesharedfolder_user_added(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == 'post_add' and len(pk_set) > 0:
        user = UserProfile.objects.get(user__pk = list(pk_set)[0]).user
        push_notification(
            [user],
            'rawdata_invited_to_private_folder',
            {
                'folder_name': instance.name,
                'folder_url': reverse_url('rawdata.privatesharedfolder_detail', kwargs = {'pk': instance.pk}),
            },
        )
コード例 #36
0
    def handle(self, *args, **kwargs):
        for user in User.objects.all():
            images = Image.objects.filter(
                user=user,
                data_source__in=["OWN_REMOTE", "AMATEUR_HOSTING"],
                remote_source=None)

            if images.count() > 0:
                push_notification([user], 'missing_remote_source', {
                    'BASE_URL': settings.BASE_URL,
                    'images': images
                })
コード例 #37
0
    def handle(self, *args, **kwargs):
        # To avoid sending too many emails, only get the users that joined on the same day of the month as today. By
        # running this script daily, you get to spread all these emails over a period of 30 days, and each user doesn't
        # get it more often than once a month.
        for user in User.objects.filter(date_joined__day = date.today().day):
            images = Image.objects.filter(user=user, data_source="UNSET")

            if images.count() > 0:
                push_notification([user], 'missing_data_source', {
                    'BASE_URL': settings.BASE_URL,
                    'images': images
                })
コード例 #38
0
    def handle(self, *args, **kwargs):
        user_subscriptions = UserSubscription.objects.filter(
            subscription__group__name__in = ['astrobin_lite', 'astrobin_premium'],
            subscription__recurrence_unit = None,
            expires = datetime.now() + timedelta(days = 7))

        for user_subscription in user_subscriptions:
            push_notification([user_subscription.user], 'expiring_subscription', {
                'user_subscription': user_subscription,
                'url': settings.BASE_URL + reverse('subscription_detail', kwargs = {
                    'object_id': user_subscription.subscription.pk
                })
            })
コード例 #39
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def rawdata_privatesharedfolder_image_added(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == 'post_add' and len(pk_set) > 0:
        invitees = instance.users.all()
        users = [instance.creator] + list(invitees)
        submitter = Image.objects.get(pk = list(pk_set)[0]).user
        users[:] = [x for x in users if x != submitter]
        push_notification(
            users,
            'rawdata_posted_image_to_private_folder',
            {
                'user_name': submitter.userprofile.get_display_name(),
                'user_url': reverse_url('user_page', kwargs = {'username': submitter.username}),
                'folder_name': instance.name,
                'folder_url': reverse_url('rawdata.privatesharedfolder_detail', kwargs = {'pk': instance.pk}),
            },
        )
コード例 #40
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def imagerevision_post_save(sender, instance, created, **kwargs):
    if created and not instance.image.is_wip:
        followers = [x.user for x in ToggleProperty.objects.filter(
            property_type = "follow",
            content_type = ContentType.objects.get_for_model(User),
            object_id = instance.user.pk)]

        push_notification(followers, 'new_image_revision',
            {
                'object_url': settings.BASE_URL + instance.get_absolute_url(),
                'originator': instance.user.userprofile.get_display_name(),
            })

        add_story(instance.image.user,
                  verb = 'VERB_UPLOADED_REVISION',
                  action_object = instance,
                  target = instance.image)
コード例 #41
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def image_post_save(sender, instance, created, **kwargs):
    profile_saved = False

    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 created:
        user_scores_index = instance.user.userprofile.get_scores()['user_scores_index']
        if user_scores_index >= 1.00 or is_lite(instance.user) or is_premium(instance.user):
            instance.moderated_when = datetime.date.today()
            instance.moderator_decision = 1
            instance.save()

        instance.user.userprofile.premium_counter += 1
        instance.user.userprofile.save()
        profile_saved = True

        if not instance.is_wip:
            followers = [x.user for x in ToggleProperty.objects.filter(
                property_type = "follow",
                content_type = ContentType.objects.get_for_model(User),
                object_id = instance.user.pk)]

            push_notification(followers, 'new_image',
                {
                    'object_url': settings.BASE_URL + instance.get_absolute_url(),
                    'originator': instance.user.userprofile.get_display_name(),
                })

            if instance.moderator_decision == 1:
                add_story(instance.user, verb = 'VERB_UPLOADED_IMAGE', action_object = instance)

    if not profile_saved:
        # Trigger update of auto_add fields
        try:
            instance.user.userprofile.save()
        except UserProfile.DoesNotExist:
            pass

    # Trigger real time search index
    instance.user.save()
コード例 #42
0
ファイル: signals.py プロジェクト: astrobin/astrobin
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
        instance.content_object.save()

    if created:
        if instance.property_type in ("like", "bookmark"):
            if instance.property_type == "like":
                verb = 'VERB_LIKED_IMAGE'
            elif instance.property_type == "bookmark":
                verb = 'VERB_BOOKMARKED_IMAGE'

            if instance.content_type == ContentType.objects.get_for_model(Image):
                image = instance.content_type.get_object_for_this_type(id = instance.object_id)
                if image.is_wip:
                    return

            add_story(instance.user,
                     verb = verb,
                     action_object = instance.content_object)

            if instance.content_type == ContentType.objects.get_for_model(Image):
                push_notification(
                    [instance.content_object.user], 'new_' + instance.property_type,
                    {
                        'url': settings.BASE_URL + instance.content_object.get_absolute_url(),
                        '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.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], 'new_follower', {
                        'object': instance.user.userprofile.get_display_name(),
                        'object_url': settings.BASE_URL + reverse_url(
                            'user_page', kwargs = {'username': instance.user.username}),
                    }
                )
コード例 #43
0
ファイル: views.py プロジェクト: astrobin/astrobin
    def post(self, request, *args, **kwargs):
        if request.is_ajax():
            group = self.get_object()
            user = UserProfile.objects.get(user__pk = self.request.POST.get('user')).user

            if user not in group.join_requests.all():
                return HttpResponseForbidden()

            group.join_requests.remove(user)
            push_notification([user], 'group_join_request_rejected',
                {
                    'group_name': group.name,
                    'url': settings.BASE_URL + reverse('group_detail', args = (group.pk,)),
                })

            return self.render_json_response({
                'member': user.pk,
            })

        # Only AJAX allowed
        return HttpResponseForbidden()
コード例 #44
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def rawdata_publicdatapool_data_added(sender, instance, action, reverse, model, pk_set, **kwargs):
    if action == 'post_add' and len(pk_set) > 0:
        contributors = [i.user for i in instance.images.all()]
        users = [instance.creator] + contributors
        submitter = RawImage.objects.get(pk = list(pk_set)[0]).user
        users[:] = [x for x in users if x != submitter]
        push_notification(
            users,
            'rawdata_posted_to_pool',
            {
                'user_name': submitter.userprofile.get_display_name(),
                'user_url': reverse_url('user_page', kwargs = {'username': submitter.username}),
                'pool_name': instance.name,
                'pool_url': reverse_url('rawdata.publicdatapool_detail', kwargs = {'pk': instance.pk}),
            },
        )

        add_story(instance.creator,
                 verb = 'VERB_ADDED_DATA_TO_DATA_POOL',
                 action_object = instance.images.all()[0],
                 target = instance)
コード例 #45
0
ファイル: signals.py プロジェクト: astrobin/astrobin
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,
            'new_topic_in_group',
            {
                'user': instance.user.userprofile.get_display_name(),
                'url': settings.BASE_URL + instance.get_absolute_url(),
                'group_url': settings.BASE_URL + reverse_url('group_detail', kwargs = {'pk': group.pk}),
                'group_name': group.name,
                'topic_title': instance.name,
            },
        )
コード例 #46
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def group_post_save(sender, instance, created, **kwargs):
    if created and instance.creator is not None:
        instance.members.add(instance.creator)
        if instance.moderated:
            instance.moderators.add(instance.creator)

        if instance.public:
            followers = [
                x.user for x in
                ToggleProperty.objects.toggleproperties_for_object(
                    "follow", UserProfile.objects.get(user__pk = instance.creator.pk).user)
            ]
            push_notification(followers, 'new_public_group_created',
                {
                    'creator': instance.creator.userprofile.get_display_name(),
                    'group_name': instance.name,
                    'url': settings.BASE_URL + reverse_url('group_detail', args = (instance.pk,)),
                })

            add_story(
                instance.creator,
                verb = 'VERB_CREATED_PUBLIC_GROUP',
                action_object = instance)
コード例 #47
0
ファイル: signals.py プロジェクト: astrobin/astrobin
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],
                'new_topic_in_group',
                {
                    'user': instance.user.userprofile.get_display_name(),
                    'url': settings.BASE_URL + instance.get_absolute_url(),
                    'group_url': reverse_url('group_detail', kwargs = {'pk': group.pk}),
                    'group_name': group.name,
                    'topic_title': instance.name,
                },
            )
コード例 #48
0
ファイル: views.py プロジェクト: astrobin/astrobin
 def post(request, *args, **kwargs):
     push_notification(
         [UserProfile.objects.get(user__username = kwargs.pop('username')).user],
         'test_notification',
         {})
     return HttpResponse("test_notification sent")
コード例 #49
0
ファイル: signals.py プロジェクト: astrobin/astrobin
def nested_comment_post_save(sender, instance, created, **kwargs):
    if created:
        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:
            image = instance.content_type.get_object_for_this_type(id = instance.object_id)
            if image.is_wip:
                return

            if instance.author != obj.user:
                push_notification(
                    [obj.user], 'new_comment',
                    {
                        'url': url,
                        'user': instance.author.userprofile.get_display_name(),
                        'user_url': settings.BASE_URL + reverse_url(
                            'user_page', kwargs = {'username': instance.author.username}),
                    }
                )

            if instance.parent and instance.parent.author != instance.author:
                push_notification(
                    [instance.parent.author], 'new_comment_reply',
                    {
                        'url': url,
                        'user': instance.author.userprofile.get_display_name(),
                        'user_url': settings.BASE_URL + reverse_url(
                            'user_page', kwargs = {'username': instance.author.username}),
                    }
                )

            add_story(instance.author,
                     verb = 'VERB_COMMENTED_IMAGE',
                     action_object = instance,
                     target = obj)

        elif model_class == Gear:
            if not instance.parent:
                gear, gear_type = get_correct_gear(obj.id)
                user_attr_lookup = {
                    'Telescope': 'telescopes',
                    'Camera': 'cameras',
                    'Mount': 'mounts',
                    'FocalReducer': 'focal_reducers',
                    'Software': 'software',
                    'Filter': 'filters',
                    'Accessory': 'accessories',
                }

                recipients = [x.user for x in UserProfile.objects.filter(
                    **{user_attr_lookup[gear_type]: gear})]
                notification = 'new_gear_discussion'
            else:
                notification = 'new_comment_reply'
                recipients = [instance.parent.author]

            push_notification(
                recipients, notification,
                {
                    'url': url,
                    'user': instance.author.userprofile.get_display_name(),
                    'user_url': settings.BASE_URL + reverse_url(
                        'user_page', kwargs = {'username': instance.author.username}),
                })

            add_story(instance.author,
                     verb = 'VERB_COMMENTED_GEAR',
                     action_object = instance,
                     target = gear)

        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()
コード例 #50
0
ファイル: signals.py プロジェクト: astrobin/astrobin
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 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, 'user_joined_public_group',
                        {
                            'user': user.userprofile.get_display_name(),
                            'group_name': instance.name,
                            'url': settings.BASE_URL + reverse_url('group_detail', args = (instance.pk,)),
                        })

                    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 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 group_sync_map.keys():
            all_members = []
            all_members_chain = chain([
                x.members.all()
                for x in Group.objects\
                    .filter(name__in = 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 group_sync_map.keys():
            all_members = []
            all_members_chain = chain([
                x.members.all()
                for x in Group.objects\
                    .filter(name__in = 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()