Ejemplo n.º 1
0
def post_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"

    post = instance
    if created:
        # The user sending the notifications.
        author = instance.author

        # Get all subscriptions for the post.
        subs = Subscription.objects.get_subs(post).exclude(user=author)

        # Generate the message from the template.
        content = html.render(name=POST_CREATED_HTML_TEMPLATE, post=post, user=author)

        # Generate the email message body.
        site = Site.objects.get_current()
        email_text = html.render(name=POST_CREATED_TEXT_TEMPLATE, post=post, user=author, site=site)


        # Create the message body.
        body = MessageBody.objects.create(author=author, subject=post.title,
                                          text=content, sent_at=post.creation_date)

        # Collects the emails for bulk sending.
        emails = []

        # This generator will produce the messages.
        def messages():
            for sub in subs:
                message = Message(user=sub.user, body=body, sent_at=body.sent_at)
                # collect to a bulk email if the subscription is by email:
                if sub.type == EMAIL_MESSAGE:
                    emails.append(
                        (body.subject, email_text, settings.DEFAULT_FROM_EMAIL, [sub.user.email])
                    )
                yield message

            # Generate an email to everyone that has a profile with all messages
            users = User.objects.filter(profile__message_prefs=ALL_MESSAGES)
            for user in users:
                emails.append(
                    (body.subject, email_text, settings.DEFAULT_FROM_EMAIL, [user.email])
                )

        # Bulk insert of all messages. Bypasses the Django ORM!
        Message.objects.bulk_create(messages(), batch_size=100)

        try:
            # Bulk sending email messages.
            results = mail.send_mass_mail(emails)
        except Exception, exc:
            logger.error("email error %s" % exc)
Ejemplo n.º 2
0
def award_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"
    award = instance

    if created:
        # The user sending the notifications.
        user = award.user
        # Generate the message from the template.
        content = html.render(name=AWARD_CREATED_HTML_TEMPLATE, award=award, user=user)

        subject = "Congratulations: you won %s" % award.badge.name

        # Create the message body.
        body = MessageBody.objects.create(author=user, subject=subject, text=content)
        message = Message.objects.create(user=user, body=body, sent_at=body.sent_at)
Ejemplo n.º 3
0
def award_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"
    award = instance

    if created:
        # The user sending the notifications.
        user = award.user
        # Generate the message from the template.
        content = html.render(name=AWARD_CREATED_HTML_TEMPLATE, award=award, user=user)

        subject = "Congratulations: you won %s" % award.badge.name

        # Create the message body.
        body = MessageBody.objects.create(author=user, subject=subject, text=content)
        message = Message.objects.create(user=user, body=body, sent_at=body.sent_at)
Ejemplo n.º 4
0
def user_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"
    from biostar.apps.messages.models import Message, MessageBody
    from biostar.apps.util import html
    from biostar.const import now

    user = instance
    if created:
        # Create a welcome message to a user
        # We do this so that tests pass, there is no admin user there
        authors = User.objects.filter(is_admin=True) or [user]
        author = authors[0]

        title = "Welcome!"
        content = html.render(name=NEW_USER_WELCOME_TEMPLATE, user=user)
        body = MessageBody.objects.create(author=author, subject=title, text=content, sent_at=now())
        message = Message(user=user, body=body, sent_at=body.sent_at)
        message.save()
Ejemplo n.º 5
0
def user_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"
    from biostar.apps.messages.models import Message, MessageBody
    from biostar.apps.util import html
    from biostar.const import now

    user = instance
    if created:
        # Create a welcome message to a user
        # We do this so that tests pass, there is no admin user there
        authors = User.objects.filter(is_admin=True) or [ user ]
        author = authors[0]

        title = "Welcome!"
        content = html.render(name=NEW_USER_WELCOME_TEMPLATE, user=user)
        body = MessageBody.objects.create(author=author, subject=title,
                                          text=content, sent_at=now())
        message = Message(user=user, body=body, sent_at=body.sent_at)
        message.save()
Ejemplo n.º 6
0
    def post(self, request=None, *args, **kwargs):

        if not request.user.is_authenticated:
            return HttpResponseForbidden()

        form = self.form_class(request.POST, user=request.user)
        if form.is_valid():
            f = form.cleaned_data
            consumption = ManualEnergyConsumption(concept=f['concept'],
                                                  consumption=f['consumption'],
                                                  user=request.user)
            consumption.save()

            messages.success(request, "Reading added successfully")
            #return HttpResponseRedirect(self.get_success_url())

            #print request.META.HTTP_REFERER
            #return HttpResponseRedirect(self.success_url)
            return HttpResponseRedirect(
                request.META.get('HTTP_REFERER', self.success_url))

        # There is an error in the form.
        return render(request, self.template_name, {'form': form})
Ejemplo n.º 7
0
def post_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"
    from biostar.apps.users.models import User

    post = instance
    if created:
        # The user sending the notifications.
        author = instance.author

        # Insert email subscriptions to users that watch these posts
        if post.is_toplevel:
            cond1 = Q(profile__message_prefs=ALL_MESSAGES)
            cond2 = Q(profile__tags__name__in=post.parse_tags())
            cond = cond1 | cond2
            for watcher in User.objects.filter(cond).exclude(id=author.id):
                sub, flag = Subscription.objects.get_or_create(post=post, user=watcher, type=EMAIL_MESSAGE)

        # Get all subscriptions for the post.
        subs = Subscription.objects.get_subs(post)

        # Generate the message from the template.
        content = html.render(name=POST_CREATED_SHORT, post=post, user=author)

        # Generate the email message body.
        site = Site.objects.get_current()
        email_text = html.render(name=POST_CREATED_TEXT, post=post, user=author, site=site)

        # Generate the html message
        email_html = html.render(name=POST_CREATED_HTML, post=post, user=author, site=site)

        # Create the message body.
        body = MessageBody.objects.create(author=author, subject=post.title,
                                          text=content, sent_at=post.creation_date)

        # Collects the emails for bulk sending.
        emails, tokens = [], []

        # This generator will produce the messages.
        def messages():
            for sub in subs:
                message = Message(user=sub.user, body=body, sent_at=body.sent_at)

                # collect to a bulk email if the subscription is by email:
                if sub.type == EMAIL_MESSAGE or sub.type == ALL_MESSAGES:
                    try:
                        token = ReplyToken(user=sub.user, post=post, token=make_uuid(8), date=now())
                        from_email = settings.EMAIL_FROM_PATTERN % (author.name, settings.DEFAULT_FROM_EMAIL)
                        from_email = from_email.encode("utf-8")
                        reply_to = settings.EMAIL_REPLY_PATTERN % token.token
                        subject = settings.EMAIL_REPLY_SUBJECT % body.subject
                        # create the email message
                        email = mail.EmailMultiAlternatives(
                            subject=subject,
                            body=email_text,
                            from_email=from_email,
                            to=[sub.user.email],
                            headers={'Reply-To': reply_to},
                        )
                        email.attach_alternative(email_html, "text/html")
                        emails.append(email)
                        tokens.append(token)
                    except Exception, exc:
                        # This here can crash the post submission hence the catchall
                        logger.error(exc)

                yield message

        # Bulk insert of all messages. Bypasses the Django ORM!
        Message.objects.bulk_create(messages(), batch_size=100)
        ReplyToken.objects.bulk_create(tokens, batch_size=100)

        try:
            # Bulk sending email messages.
            conn = mail.get_connection()
            conn.send_messages(emails)
        except Exception, exc:
            logger.error("email error %s" % exc)
Ejemplo n.º 8
0
    def post(self, request, *args, **kwargs):
        user = request.user

        post = self.get_obj()
        post = post_permissions(request, post)

        # The default return url
        response = HttpResponseRedirect(post.root.get_absolute_url())

        if not post.is_editable:
            messages.warning(request, "You may not moderate this post")
            return response

        # Initialize the form class.
        form = self.form_class(request.POST, pk=post.id)

        # Bail out on errors.
        if not form.is_valid():
            messages.error(request, "%s" % form.errors)
            return response

        # A shortcut to the clean form data.
        get = form.cleaned_data.get

        # These will be used in updates, will bypasses signals.
        query = Post.objects.filter(pk=post.id)
        root  = Post.objects.filter(pk=post.root_id)

        action = get('action')
        if action == (OPEN, TOGGLE_ACCEPT) and not user.is_moderator:
            messages.error(request, "Only a moderator may open or toggle a post")
            return response

        if action == TOGGLE_ACCEPT and post.type == Post.ANSWER:
            # Toggle post acceptance.
            post.has_accepted=not post.has_accepted
            post.save()
            has_accepted = Post.objects.filter(root=post.root, type=Post.ANSWER, has_accepted=True).count()
            root.update(has_accepted=has_accepted)
            return response

        if action == MOVE_TO_ANSWER and post.type == Post.COMMENT:
            # This is a valid action only for comments.
            messages.success(request, "Moved post to answer")
            query.update(type=Post.ANSWER, parent=post.root)
            root.update(reply_count=F("reply_count") + 1)
            return response

        if action == MOVE_TO_COMMENT and post.type == Post.ANSWER:
            # This is a valid action only for answers.
            messages.success(request, "Moved post to answer")
            query.update(type=Post.COMMENT, parent=post.root)
            root.update(reply_count=F("reply_count") - 1)
            return response

        # Some actions are valid on top level posts only.
        if action in (CLOSE_OFFTOPIC, DUPLICATE) and not post.is_toplevel:
            messages.warning(request, "You can only close or open a top level post")
            return response

        if action == OPEN:
            query.update(status=Post.OPEN)
            messages.success(request, "Opened post: %s" % post.title)
            return response

        if action in CLOSE_OFFTOPIC:
            query.update(status=Post.CLOSED)
            messages.success(request, "Closed post: %s" % post.title)
            content = html.render(name="messages/offtopic_posts.html", user=post.author, comment=get("comment"), post=post)
            comment = Post(content=content, type=Post.COMMENT, parent=post, author=user)
            comment.save()
            return response

        if action == CROSSPOST:
            content = html.render(name="messages/crossposted.html", user=post.author, comment=get("comment"), post=post)
            comment = Post(content=content, type=Post.COMMENT, parent=post, author=user)
            comment.save()
            return response

        if action == DUPLICATE:
            query.update(status=Post.CLOSED)
            posts = Post.objects.filter(id__in=get("dupe"))
            content = html.render(name="messages/duplicate_posts.html", user=post.author, comment=get("comment"), posts=posts)
            comment = Post(content=content, type=Post.COMMENT, parent=post, author=user)
            comment.save()
            return response

        if action == DELETE:

            # Delete marks a post deleted but does not remove it.
            # Remove means to delete the post from the database with no trace.

            # Posts with children or older than some value can only be deleted not removed

            # The children of a post.
            children = Post.objects.filter(parent_id=post.id).exclude(pk=post.id)

            # The condition where post can only be deleted.
            delete_only = children or post.age_in_days > 7 or post.vote_count > 1 or (post.author != user)

            if delete_only:
                # Deleted posts can be undeleted by re-opening them.
                query.update(status=Post.DELETED)
                messages.success(request, "Deleted post: %s" % post.title)
                response = HttpResponseRedirect(post.root.get_absolute_url())
            else:
                # This will remove the post. Redirect depends on the level of the post.
                url = "/" if post.is_toplevel else post.parent.get_absolute_url()
                post.delete()
                messages.success(request, "Removed post: %s" % post.title)
                response = HttpResponseRedirect(url)

            # Recompute post reply count
            post.update_reply_count()

            return response

        # By this time all actions should have been performed
        messages.warning(request, "That seems to be an invalid action for that post. \
                It is probably ok! Actions may be shown even when not valid.")
        return response
Ejemplo n.º 9
0
def post_create_messages(sender, instance, created, *args, **kwargs):
    "The actions to undertake when creating a new post"
    from biostar.apps.users.models import User

    post = instance
    if created:
        # The user sending the notifications.
        author = instance.author

        # Insert email subscriptions to users that watch these posts
        if post.is_toplevel:
            cond1 = Q(profile__message_prefs=ALL_MESSAGES)
            cond2 = Q(profile__tags__name__in=post.parse_tags())
            cond = cond1 | cond2
            for watcher in User.objects.filter(cond).exclude(id=author.id):
                sub, flag = Subscription.objects.get_or_create(
                    post=post, user=watcher, type=EMAIL_MESSAGE)

        # Get all subscriptions for the post.
        subs = Subscription.objects.get_subs(post)

        # Generate the message from the template.
        content = html.render(name=POST_CREATED_SHORT, post=post, user=author)

        # Generate the email message body.
        site = Site.objects.get_current()
        tags = ", ".join(post.root.tag_val.split(","))

        email_text = html.render(name=POST_CREATED_TEXT,
                                 post=post,
                                 user=author,
                                 site=site,
                                 tags=tags)

        # Generate the html message
        email_html = html.render(name=POST_CREATED_HTML,
                                 post=post,
                                 user=author,
                                 site=site,
                                 tags=tags)

        # Create the message body.
        body = MessageBody.objects.create(author=author,
                                          subject=post.title,
                                          text=content,
                                          sent_at=post.creation_date)

        # Collects the emails for bulk sending.
        emails, tokens = [], []

        # This generator will produce the messages.
        def messages():
            for sub in subs:
                message = Message(user=sub.user,
                                  body=body,
                                  sent_at=body.sent_at)

                # collect to a bulk email if the subscription is by email:
                if sub.type == EMAIL_MESSAGE or sub.type == ALL_MESSAGES:
                    try:
                        token = ReplyToken(user=sub.user,
                                           post=post,
                                           token=make_uuid(8),
                                           date=now())
                        from_email = settings.EMAIL_FROM_PATTERN % (
                            author.name, settings.DEFAULT_FROM_EMAIL)
                        from_email = from_email.encode("utf-8")
                        reply_to = settings.EMAIL_REPLY_PATTERN % token.token
                        subject = settings.EMAIL_REPLY_SUBJECT % body.subject
                        # create the email message
                        email = mail.EmailMultiAlternatives(
                            subject=subject,
                            body=email_text,
                            from_email=from_email,
                            to=[sub.user.email],
                            headers={'Reply-To': reply_to},
                        )
                        email.attach_alternative(email_html, "text/html")
                        emails.append(email)
                        tokens.append(token)
                    except Exception, exc:
                        # This here can crash the post submission hence the catchall
                        logger.error(exc)

                yield message

        # Bulk insert of all messages. Bypasses the Django ORM!
        Message.objects.bulk_create(messages(), batch_size=100)
        ReplyToken.objects.bulk_create(tokens, batch_size=100)

        try:
            # Bulk sending email messages.
            conn = mail.get_connection()
            conn.send_messages(emails)
        except Exception, exc:
            logger.error("email error %s" % exc)
Ejemplo n.º 10
0
def render_digest(days, text_tmpl, html_tmpl, send, options, limit=10, verbosity=1):
    from_email = settings.DEFAULT_FROM_EMAIL
    from biostar.apps.posts.models import Post
    from biostar.apps.users.models import User

    site = site = Site.objects.get_current()

    start = (now() - timedelta(days=days))

    # Posts created since the start date.
    top_posts = Post.objects.filter(status=Post.OPEN, type__in=Post.TOP_LEVEL,
                                    creation_date__gt=start).select_related('author')

    top_posts = top_posts.order_by('-view_count')[:limit]

    # Updated post created before the start date.
    upd_posts = Post.objects.filter(status=Post.OPEN,
                                    lastedit_date__gt=start)
    upd_posts = upd_posts.exclude(creation_date__gt=start, type__in=Post.TOP_LEVEL).select_related("author")
    upd_posts = upd_posts.order_by('-vote_count')[:limit]

    # Blog posts created since the start date.
    blogs = Post.objects.filter(status=Post.OPEN, type=Post.BLOG,
                                creation_date__gt=start).select_related('author')
    blogs = blogs[:limit]

    # Total post count
    total_post_count = Post.objects.filter(status=Post.OPEN).count()

    # Total user count
    total_user_count = User.objects.filter().count()

    hard_worker = User.objects.filter(post__status=Post.OPEN, post__lastedit_date__gt=start) \
        .annotate(total=Count("post")).order_by('-total').select_related("profile")
    hard_worker = hard_worker[:limit]

    params = dict(
        site=site,
        top_posts=top_posts,
        upd_posts=upd_posts,
        blogs=blogs,
        total_post_count=total_post_count,
        total_user_count=total_user_count,
        start=start.strftime("%b %d, %Y"),
        hard_worker=hard_worker,
        days=days,
    )

    text_body = html_body = ''

    if text_tmpl:
        text_body = html.render(text_tmpl, **params)
    if html_tmpl:
        html_body = html.render(html_tmpl, **params)

    if verbosity > 0:
        extras = dict(
            digest_manage=reverse("digest_manage"),
            digest_unsubscribe=reverse("digest_unsubscribe", kwargs=dict(uuid=1))
        )
        print text_body % extras
        print html_body % extras

    if send:

        logger.info('sending emails')
        emails = map(string.strip, open(send))

        def chunks(data, size):
            "Break into chunks of 100"
            for i in xrange(0, len(data), size):
                yield data[i:i+size]

        for chunk in chunks(emails, 100):
            users = User.objects.filter(email__in=chunk).select_related('profile')
            for user in users:
                try:
                    extras = dict(
                        digest_manage=reverse("digest_manage"),
                        digest_unsubscribe=reverse("digest_unsubscribe", kwargs=dict(uuid=user.profile.uuid))
                    )
                    text_content = text_body % extras
                    html_content = html_body % extras
                    subject = options['subject']
                    
                    msg = EmailMultiAlternatives(subject, text_content, from_email, [user.email])
                    msg.attach_alternative(html_content, "text/html")
                    msg.send()
                    time.sleep(0.3) # Throttle on Amazon.
                except Exception, exc:
                    logger.error('error %s sending email to %s' % (exc, user.email))