Пример #1
0
def send_message_mp(author,
                    n_topic,
                    text,
                    send_by_mail=True,
                    direct=False,
                    hat=None):
    """
    Send a post in an MP.
    Most of the param are obvious, excepted :
    * direct : send a mail directly without mp (ex : ban members who wont connect again)
    * leave : the author leave the conversation (usefull for the bot : it wont read the response a member could send)
    """

    # Getting the position of the post
    if n_topic.last_message is None:
        pos = 1
    else:
        pos = n_topic.last_message.position_in_topic + 1

    # Add the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = pos
    post.hat = hat
    post.save()

    n_topic.last_message = post
    n_topic.save()

    if not direct:
        signals.new_content.send(sender=post.__class__,
                                 instance=post,
                                 by_email=send_by_mail)

    if send_by_mail and direct:
        subject = '{} : {}'.format(settings.ZDS_APP['site']['literal_name'],
                                   n_topic.title)
        from_email = '{} <{}>'.format(
            settings.ZDS_APP['site']['literal_name'],
            settings.ZDS_APP['site']['email_noreply'])
        for recipient in n_topic.participants.values_list('email', flat=True):
            message_html = render_to_string('email/direct.html',
                                            {'msg': emarkdown(text)})
            message_txt = render_to_string('email/direct.txt', {'msg': text})

            msg = EmailMultiAlternatives(subject, message_txt, from_email,
                                         [recipient])
            msg.attach_alternative(message_html, 'text/html')
            try:
                msg.send()
            except Exception as e:
                logger.exception('Message was not sent to %s due to %s',
                                 recipient, e)

    return n_topic
Пример #2
0
    def test_get_description(self):
        """ test the return value of description """

        emarkdown(self.post3.text)
        ref = emarkdown(self.post3.text)
        posts = self.postfeed.items(obj={'tag': self.tag2.pk})
        ret = self.postfeed.item_description(item=posts[0])
        self.assertEqual(ret, ref)
Пример #3
0
def send_message_mp(
        author,
        n_topic,
        text,
        send_by_mail=True,
        direct=False):
    """
    Send a post in an MP.
    Most of the param are obvious, excepted :
    * direct : send a mail directly without mp (ex : ban members who wont connect again)
    * leave : the author leave the conversation (usefull for the bot : it wont read the response a member could send)
    """

    # Getting the position of the post
    if n_topic.last_message is None:
        pos = 1
    else:
        pos = n_topic.last_message.position_in_topic + 1

    # Add the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = pos
    post.save()

    n_topic.last_message = post
    n_topic.save()

    # send email
    if send_by_mail:
        if direct:
            subject = u"{} : {}".format(settings.ZDS_APP['site']['litteral_name'], n_topic.title)
            from_email = u"{} <{}>".format(settings.ZDS_APP['site']['litteral_name'],
                                           settings.ZDS_APP['site']['email_noreply'])
            for part in n_topic.participants.all():
                message_html = render_to_string('email/direct.html', {'msg': emarkdown(text)})
                message_txt = render_to_string('email/direct.txt', {'msg': text})

                msg = EmailMultiAlternatives(subject, message_txt, from_email, [part.email])
                msg.attach_alternative(message_html, "text/html")
                try:
                    msg.send()
                except:
                    msg = None
        else:
            for part in n_topic.participants.all():
                send_email(author, n_topic, part, pos)

            send_email(author, n_topic, n_topic.author, pos)

    return n_topic
Пример #4
0
def send_message_mp(
        author,
        n_topic,
        text,
        send_by_mail=True,
        direct=False,
        hat=None):
    """
    Send a post in an MP.
    Most of the param are obvious, excepted :
    * direct : send a mail directly without mp (ex : ban members who wont connect again)
    * leave : the author leave the conversation (usefull for the bot : it wont read the response a member could send)
    """

    # Getting the position of the post
    if n_topic.last_message is None:
        pos = 1
    else:
        pos = n_topic.last_message.position_in_topic + 1

    # Add the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = pos
    post.hat = hat
    post.save()

    n_topic.last_message = post
    n_topic.save()

    if not direct:
        signals.new_content.send(sender=post.__class__, instance=post, by_email=send_by_mail)

    if send_by_mail and direct:
        subject = '{} : {}'.format(settings.ZDS_APP['site']['literal_name'], n_topic.title)
        from_email = '{} <{}>'.format(settings.ZDS_APP['site']['literal_name'],
                                      settings.ZDS_APP['site']['email_noreply'])
        for recipient in n_topic.participants.values_list('email', flat=True):
            message_html = render_to_string('email/direct.html', {'msg': emarkdown(text)})
            message_txt = render_to_string('email/direct.txt', {'msg': text})

            msg = EmailMultiAlternatives(subject, message_txt, from_email, [recipient])
            msg.attach_alternative(message_html, 'text/html')
            try:
                msg.send()
            except Exception as e:
                logger.exception('Message was not sent to %s due to %s', recipient, e)

    return n_topic
Пример #5
0
def index_container(container, search_index_content, archive):
    """Index a container.

    :param container: container to index
    :type container: Container
    :param search_index_content: parent index
    :type search_index_content: SearchIndexContent
    :param archive: zip archive containing the content
    :type archive: zipfile.ZipFile
    """

    search_index_container = SearchIndexContainer()
    search_index_container.search_index_content = search_index_content
    search_index_container.title = container.title
    search_index_container.url_to_redirect = container.get_absolute_url_online(
    )

    # index introduction and conclusion:
    if container.introduction:
        try:
            introduction_html = emarkdown(
                get_file_content_in_zip(archive, container.introduction))
            all_html = introduction_html
            search_index_container.introduction = filter_text(
                introduction_html)
        except KeyError:
            pass

    if container.conclusion:
        try:
            conclusion_html = emarkdown(
                get_file_content_in_zip(archive, container.conclusion))
            all_html = u'{}{}'.format(all_html, conclusion_html)
            search_index_container.conclusion = filter_text(conclusion_html)
        except KeyError:
            pass

    if all_html != u'':
        search_index_container.keywords = filter_keyword(all_html)

    # index children:
    search_index_container.level = 'part'

    for child in container.children:
        if isinstance(child, Extract):
            search_index_container.level = 'chapter'  # only a chapter can contain extracts
            index_extract(child, search_index_content, archive)
        else:
            index_container(child, search_index_content, archive)

    search_index_container.save()
Пример #6
0
def index_extract(extract, search_index_content, archive):
    """Index an extract.

    :param extract: extact to index
    :type extract: Extract
    :param search_index_content: parent index
    :type search_index_content: SearchIndexContent
    :param archive: zip archive containing the content
    :type archive: zipfile.ZipFile
    """
    search_index_extract = SearchIndexExtract()
    search_index_extract.search_index_content = search_index_content
    search_index_extract.title = extract.title
    search_index_extract.url_to_redirect = extract.get_absolute_url_online()

    html = u''

    if extract.text:
        try:
            html = emarkdown(get_file_content_in_zip(archive, extract.text))
        except KeyError:
            pass

    if html:
        search_index_extract.extract_content = filter_text(html)
        search_index_extract.keywords = filter_keyword(html)

    search_index_extract.save()
Пример #7
0
def create_topic(author, forum, title, subtitle, text, key):
    """create topic in forum"""

    (tags, title_only) = get_tag_by_title(title[:80])

    # Creating the thread
    n_topic = Topic()
    n_topic.forum = forum
    n_topic.title = title_only
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.key = key
    n_topic.save()
    n_topic.add_tags(tags)
    n_topic.save()

    # Add the first message
    post = Post()
    post.topic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position = 1
    post.save()

    n_topic.last_message = post
    n_topic.save()

    follow(n_topic, user=author)

    return n_topic
Пример #8
0
def load_comment_tutorial(cli, size, fake):
    """
    Load tutorial's comments
    """
    nb_avg_posts = size * 20
    cli.stdout.write(
        u"Nombres de messages à poster en moyenne dans un tutoriel : {}".
        format(nb_avg_posts))
    tps1 = time.time()
    nb_tutorials = Tutorial.objects.filter(sha_public__isnull=False).count()
    tutorials = list(Tutorial.objects.filter(sha_public__isnull=False).all())
    nb_users = User.objects.count()
    profiles = list(Profile.objects.all())
    for i in range(0, nb_tutorials):
        nb = randint(0, nb_avg_posts * 2)
        for j in range(0, nb):
            post = NoteFactory(tutorial=tutorials[i],
                               author=profiles[j % nb_users].user,
                               position=j + 1)
            post.text = fake.paragraph(nb_sentences=5,
                                       variable_nb_sentences=True)
            post.text_html = emarkdown(post.text)
            post.save()
            sys.stdout.write(" Tuto {}/{}  \tComment {}/{}  \r".format(
                i + 1, nb_tutorials, j + 1, nb))
            sys.stdout.flush()
    tps2 = time.time()
    cli.stdout.write(u"\nFait en {} sec".format(tps2 - tps1))
Пример #9
0
 def perform_update(self, instance, data, hat=None):
     instance.hat = hat
     instance.text = data.get('text')
     instance.text_html = emarkdown(data.get('text'))
     instance.update = datetime.now()
     instance.save()
     return instance
Пример #10
0
def load_posts(cli, size, fake):
    """
    Load posts
    """
    nb_avg_posts_in_topic = size * 10
    cli.stdout.write(u"Nombres de messages à poster en moyenne dans un sujet : {}".format(nb_avg_posts_in_topic))
    tps1 = time.time()
    nb_topics = Topic.objects.count()
    if nb_topics == 0:
        cli.stdout.write(u"Il n'y a aucun topic actuellement. "
                         u"Vous devez rajouter les topics dans vos fixtures (topic)")
    else:
        topics = list(Topic.objects.all())
        nb_users = User.objects.count()
        if nb_users == 0:
            cli.stdout.write(u"Il n'y a aucun membre actuellement. "
                             u"Vous devez rajouter les membres dans vos fixtures (member)")
        else:
            profiles = list(Profile.objects.all())
            for i in range(0, nb_topics):
                nb_posts = randint(0, nb_avg_posts_in_topic * 2) + 1
                for j in range(1, nb_posts):
                    post = PostFactory(topic=topics[i], author=profiles[j % nb_users].user, position=j + 1)
                    post.text = fake.paragraph(nb_sentences=5, variable_nb_sentences=True)
                    post.text_html = emarkdown(post.text)
                    if int(nb_posts * 0.3) > 0:
                        if j % int(nb_posts * 0.3) == 0:
                            post.is_useful = True
                    post.save()
                    sys.stdout.write(" Topic {}/{}  \tPost {}/{}  \r".format(i + 1, nb_topics, j + 1, nb_posts))
                    sys.stdout.flush()
            tps2 = time.time()
            cli.stdout.write(u"\nFait en {} sec".format(tps2 - tps1))
Пример #11
0
def load_comment_content(cli, size, fake):
    """
    Load content's comments
    """
    nb_avg_posts = size * 10
    cli.stdout.write(u"Nombres de messages à poster en moyenne : {}".format(nb_avg_posts))
    tps1 = time.time()
    contents = list(PublishableContent.objects.filter(sha_public__isnull=False))
    nb_contents = len(contents)
    profiles = list(Profile.objects.all())
    nb_users = len(profiles)
    for i in range(0, nb_contents):
        nb_posts = randint(0, nb_avg_posts * 2)
        post = None
        for j in range(0, nb_posts):
            post = ContentReactionFactory(
                related_content=contents[i], author=profiles[j % nb_users].user, position=j + 1)
            post.text = fake.paragraph(nb_sentences=5, variable_nb_sentences=True)
            post.text_html = emarkdown(post.text)
            post.save()
            sys.stdout.write("Contenu {}/{}  \tCommentaire {}/{}  \r". format(i + 1, nb_contents, j + 1, nb_posts))
            sys.stdout.flush()
        contents[i].last_note = post
        contents[i].save()
    tps2 = time.time()
    cli.stdout.write(u"\nFait en {:.3f} sec".format(tps2 - tps1))
Пример #12
0
 def perform_update(self, instance, data, hat=None):
     instance.hat = hat
     instance.text = data.get("text")
     instance.text_html = emarkdown(data.get("text"))
     instance.update = datetime.now()
     instance.save()
     return instance
Пример #13
0
 def _dump_html(self, file_path, content, db_object):
     try:
         with file_path.open('w', encoding='utf-8') as f:
             f.write(emarkdown(content, db_object.js_support))
     except (UnicodeError, UnicodeEncodeError):
         raise FailureDuringPublication(
             _("Une erreur est survenue durant la publication de l'introduction de « {} »,"
               ' vérifiez le code markdown').format(self.title))
Пример #14
0
def unlock_topic(topic, msg):
    topic.is_locked = False
    main = Post.objects.filter(topic__pk=topic.pk, position=1).first()
    main.text = msg
    main.text_html = emarkdown(msg)
    main.editor = topic.author
    main.update = datetime.now()
    main.save()
    topic.save()
Пример #15
0
def MEP(article, sha):
    #convert markdown file to html file
    repo = Repo(article.get_path())
    manifest = get_blob(repo.commit(sha).tree, 'manifest.json')
    
    article_version = json.loads(manifest)
    md_file_contenu = get_blob(repo.commit(sha).tree, article_version['text'])
    
    html_file = open(os.path.join(article.get_path(), article_version['text']+'.html'), "w")
    html_file.write(emarkdown(md_file_contenu))
    html_file.close()
Пример #16
0
def edit_post(request):
    """Edit the given user's post."""
    try:
        post_pk = request.GET["message"]
    except KeyError:
        raise Http404

    post = get_object_or_404(PrivatePost, pk=post_pk)

    # Only edit last private post
    tp = get_object_or_404(PrivateTopic, pk=post.privatetopic.pk)
    last = get_object_or_404(PrivatePost, pk=tp.last_message.pk)
    if not last.pk == post.pk:
        raise PermissionDenied

    g_topic = None
    if post.position_in_topic >= 1:
        g_topic = get_object_or_404(PrivateTopic, pk=post.privatetopic.pk)

    # Making sure the user is allowed to do that. Author of the post
    # must to be the user logged.
    if post.author != request.user:
        raise PermissionDenied

    if request.method == "POST":
        if "text" not in request.POST:
            # if preview mode return on
            if "preview" in request.POST:
                return redirect(reverse("zds.mp.views.edit_post") + "?message=" + str(post_pk))
            # disallow send mp
            else:
                raise PermissionDenied

        # Using the preview button
        if "preview" in request.POST:
            form = PrivatePostForm(g_topic, request.user, initial={"text": request.POST["text"]})
            form.helper.form_action = reverse("zds.mp.views.edit_post") + "?message=" + str(post_pk)

            return render_template("mp/post/edit.html", {"post": post, "topic": g_topic, "form": form})

        # The user just sent data, handle them
        post.text = request.POST["text"]
        post.text_html = emarkdown(request.POST["text"])
        post.update = datetime.now()
        post.save()

        return redirect(post.get_absolute_url())

    else:
        form = PrivatePostForm(g_topic, request.user, initial={"text": post.text})
        form.helper.form_action = reverse("zds.mp.views.edit_post") + "?message=" + str(post_pk)
        return render_template("mp/post/edit.html", {"post": post, "topic": g_topic, "text": post.text, "form": form})
Пример #17
0
def MEP(article, sha):
    # convert markdown file to html file
    repo = Repo(article.get_path())
    manifest = get_blob(repo.commit(sha).tree, 'manifest.json')

    article_version = json_reader.loads(manifest)
    md_file_contenu = get_blob(repo.commit(sha).tree, article_version['text'])

    html_file = open(
        os.path.join(article.get_path(), article_version['text'] + '.html'),
        "w")
    html_file.write(emarkdown(md_file_contenu))
    html_file.close()
Пример #18
0
def send_post(topic, text):

    post = Post()
    post.topic = topic
    post.author = topic.author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position = topic.last_message.position + 1
    post.save()

    topic.last_message = post
    topic.save()
Пример #19
0
def __generate_topic_and_post(cli, fake, nb_avg_posts_in_topic, nb_topics, nb_users, topics, tps1):
    profiles = list(Profile.objects.all())
    for topic_index in range(0, nb_topics):
        nb_posts = randint(0, nb_avg_posts_in_topic * 2) + 1
        for post_index in range(1, nb_posts):
            post = PostFactory(
                topic=topics[topic_index], author=profiles[post_index % nb_users].user, position=post_index + 1
            )
            post.text = fake.paragraph(nb_sentences=5, variable_nb_sentences=True)
            post.text_html = emarkdown(post.text)
            post.is_useful = int(nb_posts * 0.3) > 0 and post_index % int(nb_posts * 0.3) == 0
            post.save()
            sys.stdout.write(f" Topic {topic_index + 1}/{nb_topics}  \tPost {post_index + 1}/{nb_posts}  \r")
            sys.stdout.flush()
    tps2 = time.time()
    cli.stdout.write(f"\nFait en {tps2 - tps1} sec")
Пример #20
0
 def item_description(self, item):
     # TODO: Use cached Markdown when implemented
     return emarkdown(item.text)
Пример #21
0
def answer(request):
    """Adds an answer from an user to a topic."""
    try:
        topic_pk = request.GET['sujet']
    except KeyError:
        raise Http404

    # Retrieve current topic.
    g_topic = get_object_or_404(PrivateTopic, pk=topic_pk)

    # check if user has right to answer
    if not g_topic.author == request.user \
            and request.user not in list(g_topic.participants.all()):
        raise PermissionDenied

    last_post_pk = g_topic.last_message.pk
    # Retrieve last posts of the current private topic.
    posts = PrivatePost.objects.filter(privatetopic=g_topic) \
        .prefetch_related() \
        .order_by("-pubdate")[:settings.ZDS_APP['forum']['posts_per_page']]

    # User would like preview his post or post a new post on the topic.
    if request.method == 'POST':
        data = request.POST
        newpost = last_post_pk != int(data['last_post'])

        # Using the « preview button », the « more » button or new post
        if 'preview' in data or newpost:
            form = PrivatePostForm(g_topic,
                                   request.user,
                                   initial={'text': data['text']})
            return render_template(
                'mp/post/new.html', {
                    'topic': g_topic,
                    'last_post_pk': last_post_pk,
                    'posts': posts,
                    'newpost': newpost,
                    'form': form,
                })

        # Saving the message
        else:
            form = PrivatePostForm(g_topic, request.user, request.POST)
            if form.is_valid():
                data = form.data

                post = PrivatePost()
                post.privatetopic = g_topic
                post.author = request.user
                post.text = data['text']
                post.text_html = emarkdown(data['text'])
                post.pubdate = datetime.now()
                post.position_in_topic = g_topic.get_post_count() + 1
                post.save()

                g_topic.last_message = post
                g_topic.save()

                # send email
                subject = u"{} - MP : {}".format(
                    settings.ZDS_APP['site']['abbr'], g_topic.title)
                from_email = u"{} <{}>".format(
                    settings.ZDS_APP['site']['litteral_name'],
                    settings.ZDS_APP['site']['email_noreply'])
                parts = list(g_topic.participants.all())
                parts.append(g_topic.author)
                parts.remove(request.user)
                for part in parts:
                    profile = part.profile
                    if profile.email_for_answer:
                        pos = post.position_in_topic - 1
                        last_read = PrivateTopicRead.objects.filter(
                            privatetopic=g_topic,
                            privatepost__position_in_topic=pos,
                            user=part).count()
                        if last_read > 0:
                            message_html = get_template('email/mp/new.html') \
                                .render(
                                    Context({
                                        'username': part.username,
                                        'url': settings.ZDS_APP['site']['url']
                                        + post.get_absolute_url(),
                                        'author': request.user.username
                                    }))
                            message_txt = get_template(
                                'email/mp/new.txt').render(
                                    Context({
                                        'username':
                                        part.username,
                                        'url':
                                        settings.ZDS_APP['site']['url'] +
                                        post.get_absolute_url(),
                                        'author':
                                        request.user.username
                                    }))

                            msg = EmailMultiAlternatives(
                                subject, message_txt, from_email, [part.email])
                            msg.attach_alternative(message_html, "text/html")
                            msg.send()

                return redirect(post.get_absolute_url())
            else:
                return render_template(
                    'mp/post/new.html', {
                        'topic': g_topic,
                        'last_post_pk': last_post_pk,
                        'newpost': newpost,
                        'posts': posts,
                        'form': form,
                    })

    else:
        text = ''

        # Using the quote button
        if 'cite' in request.GET:
            post_cite_pk = request.GET['cite']
            post_cite = get_object_or_404(PrivatePost, pk=post_cite_pk)

            for line in post_cite.text.splitlines():
                text = text + '> ' + line + '\n'

            text = u'{0}Source:[{1}]({2}{3})'.format(
                text, post_cite.author.username,
                settings.ZDS_APP['site']['url'], post_cite.get_absolute_url())

        form = PrivatePostForm(g_topic, request.user, initial={'text': text})
        return render_template(
            'mp/post/new.html', {
                'topic': g_topic,
                'posts': posts,
                'last_post_pk': last_post_pk,
                'form': form
            })
Пример #22
0
 def item_description(self, item):
     # TODO: Use cached Markdown when implemented
     return emarkdown(item.text)
Пример #23
0
def edit_reaction(request):
    '''
    Edit the given user's reaction
    '''
    
    try:
        reaction_pk = request.GET['message']
    except KeyError:
        raise Http404

    reaction = get_object_or_404(Reaction, pk=reaction_pk)

    g_article = None
    if reaction.position >= 1:
        g_article = get_object_or_404(Article, pk=reaction.article.pk)

    # Making sure the user is allowed to do that
    if reaction.author != request.user:
        if request.method == 'GET' and request.user.has_perm('article.change_reaction'):
            messages.add_message(
                request, messages.WARNING,
                u'Vous éditez ce message en tant que modérateur (auteur : {}).'
                u' Soyez encore plus prudent lors de l\'édition de celui-ci !'
                .format(reaction.author.username))
            reaction.alerts.all().delete()

    if request.method == 'POST':
        
        if 'delete-reaction' in request.POST:
            if reaction.author == request.user or request.user.has_perm('article.change_reaction'):
                reaction.alerts.all().delete()
                reaction.is_visible=False
                if request.user.has_perm('article.change_reaction'):
                    reaction.text_hidden=request.POST['text_hidden']
                reaction.editor = request.user
            
        if 'show-reaction' in request.POST:
            if request.user.has_perm('article.change_reaction'):
                reaction.is_visible=True
                reaction.text_hidden=''
                    
        if 'signal-reaction' in request.POST:
            if reaction.author != request.user :
                alert = Alert()
                alert.author = request.user
                alert.text=request.POST['signal-text']
                alert.pubdate = datetime.now()
                alert.save()
                reaction.alerts.add(alert)
        # Using the preview button
        if 'preview' in request.POST:
            return render_template('article/edit_reaction.html', {
                'reaction': reaction, 'article': g_article, 'text': request.POST['text'],
            })
        
        if not 'delete-reaction' in request.POST and not 'signal-reaction' in request.POST and not 'show-reaction' in request.POST:
            # The user just sent data, handle them
            if request.POST['text'].strip() !='':
                reaction.text = request.POST['text']
                reaction.text_html = emarkdown(request.POST['text'])
                reaction.update = datetime.now()
                reaction.editor = request.user
        
        reaction.save()
        
        return redirect(reaction.get_absolute_url())

    else:
        return render_template('article/edit_reaction.html', {
            'reaction': reaction, 'article': g_article, 'text': reaction.text
        })
Пример #24
0
def edit_post(request):
    """Edit the given user's post."""

    try:
        post_pk = request.GET["message"]
    except KeyError:
        raise Http404
    post = get_object_or_404(Post, pk=post_pk)
    if not post.topic.forum.can_read(request.user):
        raise PermissionDenied
    g_topic = None
    if post.position <= 1:
        g_topic = get_object_or_404(Topic, pk=post.topic.pk)

    # Making sure the user is allowed to do that. Author of the post must to be
    # the user logged.

    if post.author != request.user \
            and not request.user.has_perm("forum.change_post") and "signal_message" \
            not in request.POST:
        raise PermissionDenied
    if post.author != request.user and request.method == "GET" \
            and request.user.has_perm("forum.change_post"):
        messages.warning(request,
                         u'Vous \xe9ditez ce message en tant que '
                         u'mod\xe9rateur (auteur : {}). Soyez encore plus '
                         u'prudent lors de l\'\xe9dition de celui-ci !'
                         .format(post.author.username))
    if request.method == "POST":
        if "delete_message" in request.POST:
            if post.author == request.user \
                    or request.user.has_perm("forum.change_post"):
                post.alerts.all().delete()
                post.is_visible = False
                if request.user.has_perm("forum.change_post"):
                    post.text_hidden = request.POST["text_hidden"]
                post.editor = request.user
                messages.success(request, u"Le message est désormais masqué")
        if "show_message" in request.POST:
            if request.user.has_perm("forum.change_post"):
                post.is_visible = True
                post.text_hidden = ""
        if "signal_message" in request.POST:
            alert = Alert()
            alert.author = request.user
            alert.comment = post
            alert.scope = Alert.FORUM
            alert.text = request.POST['signal_text']
            alert.pubdate = datetime.now()
            alert.save()
            messages.success(request,
                             u'Une alerte a été envoyée '
                             u'à l\'équipe concernant '
                             u'ce message')

        # Using the preview button

        if "preview" in request.POST:
            if g_topic:
                form = TopicForm(initial={"title": request.POST["title"],
                                          "subtitle": request.POST["subtitle"],
                                          "text": request.POST["text"]})
            else:
                form = PostForm(post.topic, request.user,
                                initial={"text": request.POST["text"]})
            form.helper.form_action = reverse("zds.forum.views.edit_post") \
                + "?message=" + str(post_pk)
            return render_template("forum/post/edit.html", {
                "post": post,
                "topic": post.topic,
                "text": request.POST["text"],
                "form": form,
            })

        if "delete_message" not in request.POST and "signal_message" \
                not in request.POST and "show_message" not in request.POST:
            # The user just sent data, handle them

            if request.POST["text"].strip() != "":
                post.text = request.POST["text"]
                post.text_html = emarkdown(request.POST["text"])
                post.update = datetime.now()
                post.editor = request.user

            # Modifying the thread info

            if g_topic:
                (tags, title) = get_tag_by_title(request.POST["title"])
                g_topic.title = title
                g_topic.subtitle = request.POST["subtitle"]
                g_topic.save()
                g_topic.tags.clear()

                # add tags

                g_topic.add_tags(tags)
        post.save()
        return redirect(post.get_absolute_url())
    else:
        if g_topic:
            prefix = u""
            for tag in g_topic.tags.all():
                prefix += u"[{0}]".format(tag.title)
            form = TopicForm(
                initial={
                    "title": u"{0} {1}".format(
                        prefix,
                        g_topic.title).strip(),
                    "subtitle": g_topic.subtitle,
                    "text": post.text})
        else:
            form = PostForm(post.topic, request.user,
                            initial={"text": post.text})
        form.helper.form_action = reverse("zds.forum.views.edit_post") \
            + "?message=" + str(post_pk)
        return render_template("forum/post/edit.html", {
            "post": post,
            "topic": post.topic,
            "text": post.text,
            "form": form,
        })
Пример #25
0
def new(request):
    """Creates a new topic in a forum."""

    try:
        forum_pk = request.GET["forum"]
    except KeyError:
        raise Http404
    forum = get_object_or_404(Forum, pk=forum_pk)
    if not forum.can_read(request.user):
        raise PermissionDenied
    if request.method == "POST":

        # If the client is using the "preview" button

        if "preview" in request.POST:
            form = TopicForm(initial={"title": request.POST["title"],
                                      "subtitle": request.POST["subtitle"],
                                      "text": request.POST["text"]})
            return render_template("forum/topic/new.html",
                                   {"forum": forum,
                                    "form": form,
                                    "text": request.POST["text"]})
        form = TopicForm(request.POST)
        data = form.data
        if form.is_valid():

            # Treat title

            (tags, title) = get_tag_by_title(data["title"])

            # Creating the thread
            n_topic = Topic()
            n_topic.forum = forum
            n_topic.title = title
            n_topic.subtitle = data["subtitle"]
            n_topic.pubdate = datetime.now()
            n_topic.author = request.user
            n_topic.save()
            # add tags

            n_topic.add_tags(tags)
            n_topic.save()
            # Adding the first message

            post = Post()
            post.topic = n_topic
            post.author = request.user
            post.text = data["text"]
            post.text_html = emarkdown(request.POST["text"])
            post.pubdate = datetime.now()
            post.position = 1
            post.ip_address = get_client_ip(request)
            post.save()
            n_topic.last_message = post
            n_topic.save()

            # Follow the topic

            follow(n_topic)
            return redirect(n_topic.get_absolute_url())
    else:
        form = TopicForm()

    return render_template("forum/topic/new.html", {"forum": forum, "form": form})
Пример #26
0
def answer(request):
    """Adds an answer from a user to a topic."""

    try:
        topic_pk = request.GET["sujet"]
    except:
        # problem in variable format
        raise Http404

    # Retrieve current topic.

    g_topic = get_object_or_404(Topic, pk=topic_pk)
    if not g_topic.forum.can_read(request.user):
        raise PermissionDenied

    # Making sure posting is allowed

    if g_topic.is_locked:
        raise PermissionDenied

    # Check that the user isn't spamming

    if g_topic.antispam(request.user):
        raise PermissionDenied
    last_post_pk = g_topic.last_message.pk

    # Retrieve last posts of the current topic.
    posts = Post.objects.filter(topic=g_topic) \
    .prefetch_related() \
    .order_by("-pubdate")[:settings.POSTS_PER_PAGE]

    # User would like preview his post or post a new post on the topic.

    if request.method == "POST":
        data = request.POST
        newpost = last_post_pk != int(data["last_post"])

        # Using the « preview button », the « more » button or new post

        if "preview" in data or newpost:
            form = PostForm(g_topic, request.user, initial={"text": data["text"]})
            form.helper.form_action = reverse("zds.forum.views.answer") \
                + "?sujet=" + str(g_topic.pk)
            return render_template("forum/post/new.html", {
                "text": data["text"],
                "topic": g_topic,
                "posts": posts,
                "last_post_pk": last_post_pk,
                "newpost": newpost,
                "form": form,
            })
        else:

            # Saving the message

            form = PostForm(g_topic, request.user, request.POST)
            if form.is_valid():
                data = form.data
                post = Post()
                post.topic = g_topic
                post.author = request.user
                post.text = data["text"]
                post.text_html = emarkdown(data["text"])
                post.pubdate = datetime.now()
                post.position = g_topic.get_post_count() + 1
                post.ip_address = get_client_ip(request)
                post.save()
                g_topic.last_message = post
                g_topic.save()
                #Send mail
                subject = "ZDS - Notification : " + g_topic.title
                from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
                followers = g_topic.get_followers_by_email()
                for follower in followers:
                    receiver = follower.user
                    if receiver == request.user:
                        continue
                    pos = post.position - 1
                    last_read = TopicRead.objects.filter(
                        topic=g_topic,
                        post__position=pos,
                        user=receiver).count()
                    if last_read > 0:
                        message_html = get_template('email/notification/new.html') \
                            .render(
                                Context({
                                    'username': receiver.username,
                                    'title':g_topic.title,
                                    'url': settings.SITE_URL + post.get_absolute_url(),
                                    'author': request.user.username
                                })
                        )
                        message_txt = get_template('email/notification/new.txt').render(
                            Context({
                                'username': receiver.username,
                                'title':g_topic.title,
                                'url': settings.SITE_URL + post.get_absolute_url(),
                                'author': request.user.username
                            })
                        )
                        msg = EmailMultiAlternatives(
                            subject, message_txt, from_email, [
                                receiver.email])
                        msg.attach_alternative(message_html, "text/html")
                        msg.send()

                # Follow topic on answering
                if not g_topic.is_followed(user=request.user):
                    follow(g_topic)
                return redirect(post.get_absolute_url())
            else:
                return render_template("forum/post/new.html", {
                    "text": data["text"],
                    "topic": g_topic,
                    "posts": posts,
                    "last_post_pk": last_post_pk,
                    "newpost": newpost,
                    "form": form,
                })
    else:

        # Actions from the editor render to new.html.

        text = ""

        # Using the quote button

        if "cite" in request.GET:
            post_cite_pk = request.GET["cite"]
            post_cite = Post.objects.get(pk=post_cite_pk)
            if not post_cite.is_visible:
                raise PermissionDenied
            for line in post_cite.text.splitlines():
                text = text + "> " + line + "\n"
            text = u"{0}Source:[{1}]({2}{3})".format(
                text,
                post_cite.author.username,
                settings.SITE_URL,
                post_cite.get_absolute_url())

        form = PostForm(g_topic, request.user, initial={"text": text})
        form.helper.form_action = reverse("zds.forum.views.answer") \
            + "?sujet=" + str(g_topic.pk)
        return render_template("forum/post/new.html", {
            "topic": g_topic,
            "posts": posts,
            "last_post_pk": last_post_pk,
            "form": form,
        })
Пример #27
0
def reindex_content(published_content):
    """Index the new published version.

    .. attention::
        Note that lots of IO, memory and CPU will be used when you use this function.
        Only loop on it if you know what you are doing !

    This function looks for the archive generated in any publication and containing the content in a version that
    correspond to the public version, and then use it to create ``SearchIndex*`` objects by reading the archive.

    IO complexity is ``2 + 2 * number of containers + number of extracts`` (through a ZIP archive).

    Database query complexity is

    * on deletion : ``1 + number of containers + number of extracts`` ;
    * on addition : ``1 + number of containers + number of extracts``.

    :param published_content: Database representation of the public version of the content
    :type published_content: PublishedContent
    """

    # We just delete all index that correspond to the content
    SearchIndexContent.objects.filter(
        publishable_content__pk=published_content.content_pk).delete()

    # Load the manifest:
    if not published_content.have_zip():
        raise Exception(
            'Unable to index content due to the absence of ZIP file')

    zip_path = os.path.join(published_content.get_extra_contents_directory(),
                            published_content.content_public_slug + '.zip')

    archive = zipfile.ZipFile(zip_path)
    try:
        manifest = get_file_content_in_zip(archive, 'manifest.json')
    except KeyError:
        raise Exception(
            'Unable to index content due to the absence of manifest in ZIP file'
        )

    json_ = json_reader.loads(manifest)
    try:
        versioned = get_content_from_json(json_, None, '')
    except BadManifestError as e:
        raise Exception(e.message)
    except Exception:
        raise Exception(
            'Unable to index content due to an error while opening manifest')

    published_content.content.insert_data_in_versioned(versioned)

    # Index the content:
    search_index_content = SearchIndexContent()
    search_index_content.publishable_content = published_content.content
    search_index_content.pubdate = published_content.publication_date or datetime.now(
    )
    search_index_content.update_date = published_content.content.update_date or datetime.now(
    )

    if published_content.content.licence:
        search_index_content.licence = published_content.content.licence.title
    else:
        search_index_content.licence = ''

    if published_content.content.image:
        search_index_content.url_image = published_content.content.image.get_absolute_url(
        )
    else:
        search_index_content.url_image = ''

    search_index_content.title = versioned.title
    search_index_content.description = versioned.description

    search_index_content.save()

    # Subcategory
    for subcategory in published_content.content.subcategory.all():
        search_index_tag = SearchIndexTag()
        search_index_tag.title = subcategory.title
        search_index_tag.save()

        search_index_content.tags.add(search_index_tag)

    # Authors
    for author in published_content.content.authors.all():
        search_index_authors = SearchIndexAuthors()
        search_index_authors.username = author.username
        search_index_authors.save()

        search_index_content.authors.add(search_index_authors)

    search_index_content.url_to_redirect = published_content.get_absolute_url_online(
    )

    # Save introduction and conclusion:
    all_html = u''

    if versioned.introduction:
        try:
            introduction_html = emarkdown(
                get_file_content_in_zip(archive, versioned.introduction))
            all_html = introduction_html
            search_index_content.introduction = filter_text(introduction_html)
        except KeyError:
            pass

    if versioned.conclusion:
        try:
            conclusion_html = emarkdown(
                get_file_content_in_zip(archive, versioned.conclusion))
            all_html = u'{}{}'.format(all_html, conclusion_html)
            search_index_content.conclusion = filter_text(conclusion_html)
        except KeyError:
            pass

    if all_html != u'':
        search_index_content.keywords = filter_keyword(all_html)

    search_index_content.type = published_content.content_type.lower()
    search_index_content.save()

    # Also index children
    index_content(versioned, search_index_content, archive)

    # no need to index the next time
    published_content.content.must_reindex = False
    published_content.content.save()
Пример #28
0
def edit_reaction(request):
    """Edit the given user's reaction."""

    try:
        reaction_pk = request.GET['message']
    except KeyError:
        raise Http404
    reaction = get_object_or_404(Reaction, pk=reaction_pk)

    g_article = None
    if reaction.position >= 1:
        g_article = get_object_or_404(Article, pk=reaction.article.pk)

    # Making sure the user is allowed to do that. Author of the reaction
    # must to be the user logged.
    if reaction.author != request.user \
            and not request.user.has_perm('article.change_reaction') \
            and 'signal_message' not in request.POST:
        raise PermissionDenied

    if reaction.author != request.user \
            and request.method == 'GET' \
            and request.user.has_perm('article.change_reaction'):
        messages.add_message(
            request, messages.WARNING,
            u'Vous éditez ce message en tant que modérateur (auteur : {}).'
            u' Soyez encore plus prudent lors de l\'édition de celui-ci !'.
            format(reaction.author.username))
        reaction.alerts.all().delete()

    if request.method == 'POST':

        if 'delete_message' in request.POST:
            if reaction.author == request.user \
                    or request.user.has_perm('article.change_reaction'):
                reaction.alerts.all().delete()
                reaction.is_visible = False
                if request.user.has_perm('article.change_reaction'):
                    reaction.text_hidden = request.POST['text_hidden']
                reaction.editor = request.user

        if 'show_message' in request.POST:
            if request.user.has_perm('article.change_reaction'):
                reaction.is_visible = True
                reaction.text_hidden = ''

        if 'signal_message' in request.POST:
            alert = Alert()
            alert.author = request.user
            alert.comment = reaction
            alert.scope = Alert.ARTICLE
            alert.text = request.POST['signal_text']
            alert.pubdate = datetime.now()
            alert.save()

        # Using the preview button
        if 'preview' in request.POST:
            form = ReactionForm(g_article,
                                request.user,
                                initial={'text': request.POST['text']})
            form.helper.form_action = reverse(
                'zds.article.views.edit_reaction') + \
                '?message=' + \
                str(reaction_pk)
            return render_template('article/reaction/edit.html', {
                'reaction': reaction,
                'article': g_article,
                'form': form
            })

        if 'delete_message' not in request.POST \
                and 'signal_message' not in request.POST \
                and 'show_message' not in request.POST:
            # The user just sent data, handle them
            if request.POST['text'].strip() != '':
                reaction.text = request.POST['text']
                reaction.text_html = emarkdown(request.POST['text'])
                reaction.update = datetime.now()
                reaction.editor = request.user

        reaction.save()

        return redirect(reaction.get_absolute_url())

    else:
        form = ReactionForm(g_article,
                            request.user,
                            initial={'text': reaction.text})
        form.helper.form_action = reverse(
            'zds.article.views.edit_reaction') + '?message=' + str(reaction_pk)
        return render_template('article/reaction/edit.html', {
            'reaction': reaction,
            'article': g_article,
            'form': form
        })
Пример #29
0
def answer(request):
    """Adds an answer from a user to an article."""
    try:
        article_pk = request.GET['article']
    except KeyError:
        raise Http404

    # Retrieve current article.
    article = get_object_or_404(Article, pk=article_pk)

    # Making sure reactioning is allowed
    if article.is_locked:
        raise PermissionDenied

    # Check that the user isn't spamming
    if article.antispam(request.user):
        raise PermissionDenied

    # Retrieve 3 last reactions of the currenta article.
    reactions = Reaction.objects\
        .filter(article=article)\
        .order_by('-pubdate')[:3]

    # If there is a last reaction for the article, we save his pk.
    # Otherwise, we save 0.
    if article.last_reaction:
        last_reaction_pk = article.last_reaction.pk
    else:
        last_reaction_pk = 0

    # User would like preview his post or post a new reaction on the article.
    if request.method == 'POST':
        data = request.POST
        newreaction = last_reaction_pk != int(data['last_reaction'])

        # Using the « preview button », the « more » button or new reaction
        if 'preview' in data or newreaction:
            form = ReactionForm(article,
                                request.user,
                                initial={'text': data['text']})
            return render_template(
                'article/reaction/new.html', {
                    'article': article,
                    'last_reaction_pk': last_reaction_pk,
                    'newreaction': newreaction,
                    'form': form
                })

        # Saving the message
        else:
            form = ReactionForm(article, request.user, request.POST)
            if form.is_valid():
                data = form.data

                reaction = Reaction()
                reaction.article = article
                reaction.author = request.user
                reaction.text = data['text']
                reaction.text_html = emarkdown(data['text'])
                reaction.pubdate = datetime.now()
                reaction.position = article.get_reaction_count() + 1
                reaction.ip_address = get_client_ip(request)
                reaction.save()

                article.last_reaction = reaction
                article.save()

                return redirect(reaction.get_absolute_url())
            else:
                return render_template(
                    'article/reaction/new.html', {
                        'article': article,
                        'last_reaction_pk': last_reaction_pk,
                        'newreaction': newreaction,
                        'form': form
                    })

    # Actions from the editor render to new.html.
    else:
        text = ''

        # Using the quote button
        if 'cite' in request.GET:
            reaction_cite_pk = request.GET['cite']
            reaction_cite = Reaction.objects.get(pk=reaction_cite_pk)
            if not reaction_cite.is_visible:
                raise PermissionDenied

            for line in reaction_cite.text.splitlines():
                text = text + '> ' + line + '\n'

            text = u'{0}Source:[{1}]({2}{3})'.format(
                text, reaction_cite.author.username, settings.SITE_URL,
                reaction_cite.get_absolute_url())

        form = ReactionForm(article, request.user, initial={'text': text})
        return render_template(
            'article/reaction/new.html', {
                'article': article,
                'reactions': reactions,
                'last_reaction_pk': last_reaction_pk,
                'form': form
            })
Пример #30
0
def send_mp(
        author,
        users,
        title,
        subtitle,
        text,
        send_by_mail=True,
        leave=True,
        direct=False):
    """Send MP at members."""

    # Creating the thread
    n_topic = PrivateTopic()
    n_topic.title = title[:80]
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.save()

    # Add all participants on the MP.
    for part in users:
        n_topic.participants.add(part)

    # Addi the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = 1
    post.save()

    n_topic.last_message = post
    n_topic.save()

    # send email
    if send_by_mail:
        if direct:
            subject = "ZDS : " + n_topic.title
            from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
            for part in users:
                message_html = get_template('email/mp/direct.html').render(
                    Context({
                        'msg': emarkdown(text)
                    })
                )
                message_txt = get_template('email/mp/direct.txt').render(
                    Context({
                        'msg': text
                    })
                )

                msg = EmailMultiAlternatives(
                    subject, message_txt, from_email, [
                        part.email])
                msg.attach_alternative(message_html, "text/html")
                try:
                    msg.send()
                except:
                    msg = None
        else:
            subject = "ZDS - MP: " + n_topic.title
            from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
            for part in users:
                message_html = get_template('email/mp/new.html').render(
                    Context({
                        'username': part.username,
                        'url': settings.SITE_URL + n_topic.get_absolute_url(),
                        'author': author.username
                    })
                )
                message_txt = get_template('email/mp/new.txt').render(
                    Context({
                        'username': part.username,
                        'url': settings.SITE_URL + n_topic.get_absolute_url(),
                        'author': author.username
                    })
                )

                msg = EmailMultiAlternatives(
                    subject, message_txt, from_email, [
                        part.email])
                msg.attach_alternative(message_html, "text/html")
                try:
                    msg.send()
                except:
                    msg = None
    if leave:
        move = n_topic.participants.first()
        n_topic.author = move
        n_topic.participants.remove(move)
        n_topic.save()

    return n_topic
Пример #31
0
def send_message_mp(author,
                    n_topic,
                    text,
                    send_by_mail=True,
                    direct=False,
                    hat=None,
                    no_notification_for=None):
    """
    Send a post in an MP.

    :param author: sender of the private message
    :param n_topic: topic in which it will be sent
    :param text: content of the message
    :param send_by_mail: if True, also notify by email
    :param direct: send a mail directly without private message (ex : banned members who won't connect again)
    :param hat: hat attached to the message
    :param no_notification_for: list of participants who won't be notified of the message
    """

    # Getting the position of the post
    if n_topic.last_message is None:
        pos = 1
    else:
        pos = n_topic.last_message.position_in_topic + 1

    # Add the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = pos
    post.hat = hat
    post.save()

    n_topic.last_message = post
    n_topic.save()

    if not direct:
        signals.message_added.send(sender=post.__class__,
                                   post=post,
                                   by_email=send_by_mail,
                                   no_notification_for=no_notification_for)

    if send_by_mail and direct:
        subject = "{} : {}".format(settings.ZDS_APP["site"]["literal_name"],
                                   n_topic.title)
        from_email = "{} <{}>".format(
            settings.ZDS_APP["site"]["literal_name"],
            settings.ZDS_APP["site"]["email_noreply"])
        for recipient in n_topic.participants.values_list("email", flat=True):
            message_html = render_to_string("email/direct.html",
                                            {"msg": emarkdown(text)})
            message_txt = render_to_string("email/direct.txt", {"msg": text})

            msg = EmailMultiAlternatives(subject, message_txt, from_email,
                                         [recipient])
            msg.attach_alternative(message_html, "text/html")
            try:
                msg.send()
            except Exception as e:
                logger.exception("Message was not sent to %s due to %s",
                                 recipient, e)
    if no_notification_for:
        if not isinstance(no_notification_for, list):
            no_notification_for = [no_notification_for]
        for not_notified_user in no_notification_for:
            mark_read(n_topic, not_notified_user)

    # There's no need to inform of the new participant
    # because participants are already notified through the `message_added` signal.
    # If we tried to add the bot, that's fine (a better solution would be welcome though)
    with suppress(NotReachableError):
        n_topic.add_participant(author, silent=True)
        n_topic.save()

    return n_topic
Пример #32
0
def edit_post(request):
    """Edit the given user's post."""
    try:
        post_pk = request.GET['message']
    except KeyError:
        raise Http404

    post = get_object_or_404(PrivatePost, pk=post_pk)

    # Only edit last private post
    tp = get_object_or_404(PrivateTopic, pk=post.privatetopic.pk)
    last = get_object_or_404(PrivatePost, pk=tp.last_message.pk)
    if not last.pk == post.pk:
        raise PermissionDenied

    g_topic = None
    if post.position_in_topic >= 1:
        g_topic = get_object_or_404(PrivateTopic, pk=post.privatetopic.pk)

    # Making sure the user is allowed to do that. Author of the post
    # must to be the user logged.
    if post.author != request.user:
        raise PermissionDenied

    if request.method == 'POST':
        if 'text' not in request.POST:
            # if preview mode return on
            if 'preview' in request.POST:
                return redirect(
                    reverse('zds.mp.views.edit_post') + '?message=' +
                    str(post_pk))
            # disallow send mp
            else:
                raise PermissionDenied

        # Using the preview button
        if 'preview' in request.POST:
            form = PrivatePostForm(g_topic,
                                   request.user,
                                   initial={'text': request.POST['text']})
            form.helper.form_action = reverse(
                'zds.mp.views.edit_post') + '?message=' + str(post_pk)

            return render_template('mp/post/edit.html', {
                'post': post,
                'topic': g_topic,
                'form': form,
            })

        # The user just sent data, handle them
        post.text = request.POST['text']
        post.text_html = emarkdown(request.POST['text'])
        post.update = datetime.now()
        post.save()

        return redirect(post.get_absolute_url())

    else:
        form = PrivatePostForm(g_topic,
                               request.user,
                               initial={'text': post.text})
        form.helper.form_action = reverse(
            'zds.mp.views.edit_post') + '?message=' + str(post_pk)
        return render_template('mp/post/edit.html', {
            'post': post,
            'topic': g_topic,
            'text': post.text,
            'form': form,
        })
Пример #33
0
def publish_container(db_object,
                      base_dir,
                      container,
                      template='tutorialv2/export/chapter.html',
                      file_ext='html',
                      image_callback=None,
                      **ctx):
    """ 'Publish' a given container, in a recursive way

    :param image_callback: callback used to change images tags on the created html
    :type image_callback: callable
    :param db_object: database representation of the content
    :type db_object: PublishableContent
    :param base_dir: directory of the top container
    :type base_dir: str
    :param template: the django template we will use to produce chapter export to html.
    :param container: a given container
    :type container: Container
    :param file_ext: output file extension
    :raise FailureDuringPublication: if anything goes wrong
    """

    from zds.tutorialv2.models.versioned import Container
    from zds.tutorialv2.publication_utils import FailureDuringPublication
    path_to_title_dict = collections.OrderedDict()
    ctx['relative'] = ctx.get('relative', '.')
    if not isinstance(container, Container):
        raise FailureDuringPublication(_(u"Le conteneur n'en est pas un !"))

    # jsFiddle support
    is_js = ''
    if db_object.js_support:
        is_js = 'js'

    current_dir = path.dirname(
        path.join(base_dir, container.get_prod_path(relative=True)))

    if not path.isdir(current_dir):
        makedirs(current_dir)

    if container.has_extracts(
    ):  # the container can be rendered in one template
        img_relative_path = '..' if ctx[
            'relative'] == '.' else '../' + ctx['relative']
        wrapped_image_callback = image_callback(
            img_relative_path) if image_callback else image_callback
        args = {'container': container, 'is_js': is_js}
        args.update(ctx)
        parsed = render_to_string(template, args)
        write_chapter_file(base_dir, container,
                           Path(container.get_prod_path(True, file_ext)),
                           parsed, path_to_title_dict, wrapped_image_callback)
        for extract in container.children:
            extract.text = None

        container.introduction = None
        container.conclusion = None

    else:  # separate render of introduction and conclusion
        wrapped_image_callback = image_callback(
            ctx['relative']) if image_callback else image_callback
        # create subdirectory
        if not path.isdir(current_dir):
            makedirs(current_dir)
        ctx['relative'] = '../' + ctx['relative']
        if container.introduction and container.get_introduction():
            part_path = Path(container.get_prod_path(relative=True),
                             'introduction.' + file_ext)
            parsed = emarkdown(container.get_introduction(),
                               db_object.js_support)
            container.introduction = str(part_path)
            write_chapter_file(base_dir, container, part_path, parsed,
                               path_to_title_dict, wrapped_image_callback)
        children = copy.copy(container.children)
        container.children = []
        container.children_dict = {}
        for child in filter(lambda c: c.ready_to_publish, children):

            altered_version = copy.copy(child)
            container.children.append(altered_version)
            container.children_dict[altered_version.slug] = altered_version
            result = publish_container(db_object,
                                       base_dir,
                                       altered_version,
                                       file_ext=file_ext,
                                       image_callback=image_callback,
                                       template=template,
                                       **ctx)
            path_to_title_dict.update(result)
        if container.conclusion and container.get_conclusion():
            part_path = Path(container.get_prod_path(relative=True),
                             'conclusion.' + file_ext)
            parsed = emarkdown(container.get_conclusion(),
                               db_object.js_support)
            container.conclusion = str(part_path)
            write_chapter_file(base_dir, container, part_path, parsed,
                               path_to_title_dict, wrapped_image_callback)

    return path_to_title_dict
Пример #34
0
def new(request):
    """Creates a new topic in a forum."""

    try:
        forum_pk = request.GET["forum"]
    except:
        # problem in variable format
        raise Http404
    forum = get_object_or_404(Forum, pk=forum_pk)
    if not forum.can_read(request.user):
        raise PermissionDenied
    if request.method == "POST":

        # If the client is using the "preview" button

        if "preview" in request.POST:
            form = TopicForm(initial={"title": request.POST["title"],
                                      "subtitle": request.POST["subtitle"],
                                      "text": request.POST["text"]})
            return render_template("forum/topic/new.html",
                                   {"forum": forum,
                                    "form": form,
                                    "text": request.POST["text"]})
        form = TopicForm(request.POST)
        data = form.data
        if form.is_valid():

            # Treat title

            (tags, title) = get_tag_by_title(data["title"])

            # Creating the thread
            n_topic = Topic()
            n_topic.forum = forum
            n_topic.title = title
            n_topic.subtitle = data["subtitle"]
            n_topic.pubdate = datetime.now()
            n_topic.author = request.user
            n_topic.save()
            # add tags

            n_topic.add_tags(tags)
            n_topic.save()
            # Adding the first message

            post = Post()
            post.topic = n_topic
            post.author = request.user
            post.text = data["text"]
            post.text_html = emarkdown(request.POST["text"])
            post.pubdate = datetime.now()
            post.position = 1
            post.ip_address = get_client_ip(request)
            post.save()
            n_topic.last_message = post
            n_topic.save()

            # Follow the topic

            follow(n_topic)
            return redirect(n_topic.get_absolute_url())
    else:
        form = TopicForm()

    return render_template("forum/topic/new.html", {"forum": forum, "form": form})
Пример #35
0
def edit_reaction(request):
    """Edit the given user's reaction."""

    try:
        reaction_pk = request.GET['message']
    except KeyError:
        raise Http404
    reaction = get_object_or_404(Reaction, pk=reaction_pk)

    g_article = None
    if reaction.position >= 1:
        g_article = get_object_or_404(Article, pk=reaction.article.pk)

    # Making sure the user is allowed to do that. Author of the reaction
    # must to be the user logged.
    if reaction.author != request.user \
            and not request.user.has_perm('article.change_reaction') \
            and 'signal_message' not in request.POST:
        raise PermissionDenied

    if reaction.author != request.user \
            and request.method == 'GET' \
            and request.user.has_perm('article.change_reaction'):
        messages.add_message(
            request, messages.WARNING,
            u'Vous éditez ce message en tant que modérateur (auteur : {}).'
            u' Soyez encore plus prudent lors de l\'édition de celui-ci !'
            .format(reaction.author.username))
        reaction.alerts.all().delete()

    if request.method == 'POST':

        if 'delete_message' in request.POST:
            if reaction.author == request.user \
                    or request.user.has_perm('article.change_reaction'):
                reaction.alerts.all().delete()
                reaction.is_visible = False
                if request.user.has_perm('article.change_reaction'):
                    reaction.text_hidden = request.POST['text_hidden']
                reaction.editor = request.user

        if 'show_message' in request.POST:
            if request.user.has_perm('article.change_reaction'):
                reaction.is_visible = True
                reaction.text_hidden = ''

        if 'signal_message' in request.POST:
            alert = Alert()
            alert.author = request.user
            alert.comment = reaction
            alert.scope = Alert.ARTICLE
            alert.text = request.POST['signal_text']
            alert.pubdate = datetime.now()
            alert.save()

        # Using the preview button
        if 'preview' in request.POST:
            form = ReactionForm(g_article, request.user, initial={
                'text': request.POST['text']
            })
            form.helper.form_action = reverse(
                'zds.article.views.edit_reaction') + \
                '?message=' + \
                str(reaction_pk)
            return render_template('article/reaction/edit.html', {
                'reaction': reaction,
                'article': g_article,
                'form': form
            })

        if 'delete_message' not in request.POST \
                and 'signal_message' not in request.POST \
                and 'show_message' not in request.POST:
            # The user just sent data, handle them
            if request.POST['text'].strip() != '':
                reaction.text = request.POST['text']
                reaction.text_html = emarkdown(request.POST['text'])
                reaction.update = datetime.now()
                reaction.editor = request.user

        reaction.save()

        return redirect(reaction.get_absolute_url())

    else:
        form = ReactionForm(g_article, request.user, initial={
            'text': reaction.text
        })
        form.helper.form_action = reverse(
            'zds.article.views.edit_reaction') + '?message=' + str(reaction_pk)
        return render_template('article/reaction/edit.html', {
            'reaction': reaction,
            'article': g_article,
            'form': form
        })
Пример #36
0
def edit_post(request):
    """Edit the given user's post."""

    try:
        post_pk = request.GET["message"]
    except:
        # problem in variable format
        raise Http404
    post = get_object_or_404(Post, pk=post_pk)
    if not post.topic.forum.can_read(request.user):
        raise PermissionDenied
    g_topic = None
    if post.position <= 1:
        g_topic = get_object_or_404(Topic, pk=post.topic.pk)

    # Making sure the user is allowed to do that. Author of the post must to be
    # the user logged.

    if post.author != request.user \
            and not request.user.has_perm("forum.change_post") and "signal_message" \
            not in request.POST:
        raise PermissionDenied
    if post.author != request.user and request.method == "GET" \
            and request.user.has_perm("forum.change_post"):
        messages.warning(request,
                         u'Vous \xe9ditez ce message en tant que '
                         u'mod\xe9rateur (auteur : {}). Soyez encore plus '
                         u'prudent lors de l\'\xe9dition de celui-ci !'
                         .format(post.author.username))
    if request.method == "POST":
        if "delete_message" in request.POST:
            if post.author == request.user \
                    or request.user.has_perm("forum.change_post"):
                post.alerts.all().delete()
                post.is_visible = False
                if request.user.has_perm("forum.change_post"):
                    post.text_hidden = request.POST["text_hidden"]
                post.editor = request.user
                messages.success(request, u"Le message est désormais masqué")
        if "show_message" in request.POST:
            if request.user.has_perm("forum.change_post"):
                post.is_visible = True
                post.text_hidden = ""
        if "signal_message" in request.POST:
            alert = Alert()
            alert.author = request.user
            alert.comment = post
            alert.scope = Alert.FORUM
            alert.text = request.POST['signal_text']
            alert.pubdate = datetime.now()
            alert.save()
            messages.success(request,
                             u'Une alerte a été envoyée '
                             u'à l\'équipe concernant '
                             u'ce message')

        # Using the preview button

        if "preview" in request.POST:
            if g_topic:
                form = TopicForm(initial={"title": request.POST["title"],
                                          "subtitle": request.POST["subtitle"],
                                          "text": request.POST["text"]})
            else:
                form = PostForm(post.topic, request.user,
                                initial={"text": request.POST["text"]})
            form.helper.form_action = reverse("zds.forum.views.edit_post") \
                + "?message=" + str(post_pk)
            return render_template("forum/post/edit.html", {
                "post": post,
                "topic": post.topic,
                "text": request.POST["text"],
                "form": form,
            })

        if "delete_message" not in request.POST and "signal_message" \
                not in request.POST and "show_message" not in request.POST:
            # The user just sent data, handle them

            if request.POST["text"].strip() != "":
                post.text = request.POST["text"]
                post.text_html = emarkdown(request.POST["text"])
                post.update = datetime.now()
                post.editor = request.user

            # Modifying the thread info

            if g_topic:
                (tags, title) = get_tag_by_title(request.POST["title"])
                g_topic.title = title
                g_topic.subtitle = request.POST["subtitle"]
                g_topic.save()
                g_topic.tags.clear()

                # add tags

                g_topic.add_tags(tags)
        post.save()
        return redirect(post.get_absolute_url())
    else:
        if g_topic:
            prefix = u""
            for tag in g_topic.tags.all():
                prefix += u"[{0}]".format(tag.title)
            form = TopicForm(
                initial={
                    "title": u"{0} {1}".format(
                        prefix,
                        g_topic.title).strip(),
                    "subtitle": g_topic.subtitle,
                    "text": post.text})
        else:
            form = PostForm(post.topic, request.user,
                            initial={"text": post.text})
        form.helper.form_action = reverse("zds.forum.views.edit_post") \
            + "?message=" + str(post_pk)
        return render_template("forum/post/edit.html", {
            "post": post,
            "topic": post.topic,
            "text": post.text,
            "form": form,
        })
Пример #37
0
def answer(request):
    """Adds an answer from a user to an article."""
    try:
        article_pk = request.GET['article']
    except KeyError:
        raise Http404

    # Retrieve current article.
    article = get_object_or_404(Article, pk=article_pk)

    # Making sure reactioning is allowed
    if article.is_locked:
        raise PermissionDenied

    # Check that the user isn't spamming
    if article.antispam(request.user):
        raise PermissionDenied

    # Retrieve 3 last reactions of the currenta article.
    reactions = Reaction.objects\
        .filter(article=article)\
        .order_by('-pubdate')[:3]

    # If there is a last reaction for the article, we save his pk.
    # Otherwise, we save 0.
    if article.last_reaction:
        last_reaction_pk = article.last_reaction.pk
    else:
        last_reaction_pk = 0

    # User would like preview his post or post a new reaction on the article.
    if request.method == 'POST':
        data = request.POST
        newreaction = last_reaction_pk != int(data['last_reaction'])

        # Using the « preview button », the « more » button or new reaction
        if 'preview' in data or newreaction:
            form = ReactionForm(article, request.user, initial={
                'text': data['text']
            })
            return render_template('article/reaction/new.html', {
                'article': article,
                'last_reaction_pk': last_reaction_pk,
                'newreaction': newreaction,
                'form': form
            })

        # Saving the message
        else:
            form = ReactionForm(article, request.user, request.POST)
            if form.is_valid():
                data = form.data

                reaction = Reaction()
                reaction.article = article
                reaction.author = request.user
                reaction.text = data['text']
                reaction.text_html = emarkdown(data['text'])
                reaction.pubdate = datetime.now()
                reaction.position = article.get_reaction_count() + 1
                reaction.ip_address = get_client_ip(request)
                reaction.save()

                article.last_reaction = reaction
                article.save()

                return redirect(reaction.get_absolute_url())
            else:
                return render_template('article/reaction/new.html', {
                    'article': article,
                    'last_reaction_pk': last_reaction_pk,
                    'newreaction': newreaction,
                    'form': form
                })

    # Actions from the editor render to new.html.
    else:
        text = ''

        # Using the quote button
        if 'cite' in request.GET:
            reaction_cite_pk = request.GET['cite']
            reaction_cite = Reaction.objects.get(pk=reaction_cite_pk)
            if not reaction_cite.is_visible:
                raise PermissionDenied

            for line in reaction_cite.text.splitlines():
                text = text + '> ' + line + '\n'

            text = u'{0}Source:[{1}]({2}{3})'.format(
                text,
                reaction_cite.author.username,
                settings.SITE_URL,
                reaction_cite.get_absolute_url())

        form = ReactionForm(article, request.user, initial={
            'text': text
        })
        return render_template('article/reaction/new.html', {
            'article': article,
            'reactions': reactions,
            'last_reaction_pk': last_reaction_pk,
            'form': form
        })
Пример #38
0
def answer(request):
    """Adds an answer from a user to a topic."""

    try:
        topic_pk = request.GET["sujet"]
    except KeyError:
        raise Http404

    # Retrieve current topic.

    g_topic = get_object_or_404(Topic, pk=topic_pk)
    if not g_topic.forum.can_read(request.user):
        raise PermissionDenied

    # Making sure posting is allowed

    if g_topic.is_locked:
        raise PermissionDenied

    # Check that the user isn't spamming

    if g_topic.antispam(request.user):
        raise PermissionDenied
    last_post_pk = g_topic.last_message.pk

    # Retrieve 10 last posts of the current topic.

    posts = \
        Post.objects.filter(topic=g_topic) \
        .prefetch_related() \
        .order_by("-pubdate"
                  )[:10]

    # User would like preview his post or post a new post on the topic.

    if request.method == "POST":
        data = request.POST
        newpost = last_post_pk != int(data["last_post"])

        # Using the « preview button », the « more » button or new post

        if "preview" in data or newpost:
            form = PostForm(g_topic, request.user, initial={"text": data["text"
                                                                         ]})
            form.helper.form_action = reverse("zds.forum.views.answer") \
                + "?sujet=" + str(g_topic.pk)
            return render_template("forum/post/new.html", {
                "text": data["text"],
                "topic": g_topic,
                "posts": posts,
                "last_post_pk": last_post_pk,
                "newpost": newpost,
                "form": form,
            })
        else:

            # Saving the message

            form = PostForm(g_topic, request.user, request.POST)
            if form.is_valid():
                data = form.data
                post = Post()
                post.topic = g_topic
                post.author = request.user
                post.text = data["text"]
                post.text_html = emarkdown(data["text"])
                post.pubdate = datetime.now()
                post.position = g_topic.get_post_count() + 1
                post.ip_address = get_client_ip(request)
                post.save()
                g_topic.last_message = post
                g_topic.save()
                #Send mail
                subject = "ZDS - Notification : " + g_topic.title
                from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
                followers = g_topic.get_followers_by_email()
                for follower in followers:
                    receiver = follower.user
                    if receiver == request.user:
                        continue
                    pos = post.position - 1
                    last_read = TopicRead.objects.filter(
                        topic=g_topic,
                        post__position=pos,
                        user=receiver).count()
                    if last_read > 0:
                        message_html = get_template('email/notification/new.html') \
                            .render(
                                Context({
                                    'username': receiver.username,
                                    'title':g_topic.title,
                                    'url': settings.SITE_URL + post.get_absolute_url(),
                                    'author': request.user.username
                                })
                        )
                        message_txt = get_template('email/notification/new.txt').render(
                            Context({
                                'username': receiver.username,
                                'title':g_topic.title,
                                'url': settings.SITE_URL + post.get_absolute_url(),
                                'author': request.user.username
                            })
                        )
                        msg = EmailMultiAlternatives(
                            subject, message_txt, from_email, [
                                receiver.email])
                        msg.attach_alternative(message_html, "text/html")
                        msg.send()

                # Follow topic on answering
                if not g_topic.is_followed(user=request.user):
                    follow(g_topic)
                return redirect(post.get_absolute_url())
            else:
                return render_template("forum/post/new.html", {
                    "text": data["text"],
                    "topic": g_topic,
                    "posts": posts,
                    "last_post_pk": last_post_pk,
                    "newpost": newpost,
                    "form": form,
                })
    else:

        # Actions from the editor render to new.html.

        text = ""

        # Using the quote button

        if "cite" in request.GET:
            post_cite_pk = request.GET["cite"]
            post_cite = Post.objects.get(pk=post_cite_pk)
            if not post_cite.is_visible:
                raise PermissionDenied
            for line in post_cite.text.splitlines():
                text = text + "> " + line + "\n"
            text = u"{0}Source:[{1}]({2}{3})".format(
                text,
                post_cite.author.username,
                settings.SITE_URL,
                post_cite.get_absolute_url())

        form = PostForm(g_topic, request.user, initial={"text": text})
        form.helper.form_action = reverse("zds.forum.views.answer") \
            + "?sujet=" + str(g_topic.pk)
        return render_template("forum/post/new.html", {
            "topic": g_topic,
            "posts": posts,
            "last_post_pk": last_post_pk,
            "form": form,
        })
Пример #39
0
def answer(request):
    """Adds an answer from an user to a topic."""
    try:
        topic_pk = request.GET['sujet']
    except KeyError:
        raise Http404

    # Retrieve current topic.
    g_topic = get_object_or_404(PrivateTopic, pk=topic_pk)

    # Retrieve 3 last posts of the currenta topic.
    posts = PrivatePost.objects\
        .filter(privatetopic=g_topic)\
        .order_by('-pubdate')[:3]
    last_post_pk = g_topic.last_message.pk

    # User would like preview his post or post a new post on the topic.
    if request.method == 'POST':
        data = request.POST
        newpost = last_post_pk != int(data['last_post'])

        # Using the « preview button », the « more » button or new post
        if 'preview' in data or newpost:
            form = PrivatePostForm(g_topic, request.user, initial={
                'text': data['text']
            })
            return render_template('mp/post/new.html', {
                'topic': g_topic,
                'last_post_pk': last_post_pk,
                'newpost': newpost,
                'form': form,
            })

        # Saving the message
        else:
            form = PrivatePostForm(g_topic, request.user, request.POST)
            if form.is_valid():
                data = form.data

                post = PrivatePost()
                post.privatetopic = g_topic
                post.author = request.user
                post.text = data['text']
                post.text_html = emarkdown(data['text'])
                post.pubdate = datetime.now()
                post.position_in_topic = g_topic.get_post_count() + 1
                post.save()

                g_topic.last_message = post
                g_topic.save()

                # send email
                subject = "ZDS - MP : " + g_topic.title
                from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
                parts = list(g_topic.participants.all())
                parts.append(g_topic.author)
                parts.remove(request.user)
                for part in parts:
                    profile = part.profile
                    if profile.email_for_answer:
                        pos = post.position_in_topic - 1
                        last_read = PrivateTopicRead.objects.filter(
                            privatetopic=g_topic,
                            privatepost__position_in_topic=pos,
                            user=part).count()
                        if last_read > 0:
                            message_html = get_template('email/mp/new.html') \
                                .render(
                                    Context({
                                        'username': part.username,
                                        'url': settings.SITE_URL
                                        + post.get_absolute_url(),
                                        'author': request.user.username
                                    })
                            )
                            message_txt = get_template('email/mp/new.txt').render(
                                Context({
                                    'username': part.username,
                                    'url': settings.SITE_URL
                                    + post.get_absolute_url(),
                                    'author': request.user.username
                                })
                            )

                            msg = EmailMultiAlternatives(
                                subject, message_txt, from_email, [
                                    part.email])
                            msg.attach_alternative(message_html, "text/html")
                            msg.send()

                return redirect(post.get_absolute_url())
            else:
                return render_template('mp/post/new.html', {
                    'topic': g_topic,
                    'last_post_pk': last_post_pk,
                    'newpost': newpost,
                    'form': form,
                })

    else:
        text = ''

        # Using the quote button
        if 'cite' in request.GET:
            post_cite_pk = request.GET['cite']
            post_cite = PrivatePost.objects.get(pk=post_cite_pk)

            for line in post_cite.text.splitlines():
                text = text + '> ' + line + '\n'

            text = u'{0}Source:[{1}]({2}{3})'.format(
                text,
                post_cite.author.username,
                settings.SITE_URL,
                post_cite.get_absolute_url())

        form = PrivatePostForm(g_topic, request.user, initial={
            'text': text
        })
        return render_template('mp/post/new.html', {
            'topic': g_topic,
            'posts': posts,
            'last_post_pk': last_post_pk,
            'form': form
        })
Пример #40
0
def send_mp(author,
            users,
            title,
            subtitle,
            text,
            send_by_mail=True,
            leave=True,
            direct=False):
    """Send MP at members."""

    # Creating the thread
    n_topic = PrivateTopic()
    n_topic.title = title[:80]
    n_topic.subtitle = subtitle
    n_topic.pubdate = datetime.now()
    n_topic.author = author
    n_topic.save()

    # Add all participants on the MP.
    for part in users:
        n_topic.participants.add(part)

    # Addi the first message
    post = PrivatePost()
    post.privatetopic = n_topic
    post.author = author
    post.text = text
    post.text_html = emarkdown(text)
    post.pubdate = datetime.now()
    post.position_in_topic = 1
    post.save()

    n_topic.last_message = post
    n_topic.save()

    # send email
    if send_by_mail:
        if direct:
            subject = "ZDS : " + n_topic.title
            from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
            for part in users:
                message_html = get_template('email/mp/direct.html').render(
                    Context({'msg': emarkdown(text)}))
                message_txt = get_template('email/mp/direct.txt').render(
                    Context({'msg': text}))

                msg = EmailMultiAlternatives(subject, message_txt, from_email,
                                             [part.email])
                msg.attach_alternative(message_html, "text/html")
                try:
                    msg.send()
                except:
                    msg = None
        else:
            subject = "ZDS - MP: " + n_topic.title
            from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
            for part in users:
                message_html = get_template('email/mp/new.html').render(
                    Context({
                        'username':
                        part.username,
                        'url':
                        settings.SITE_URL + n_topic.get_absolute_url(),
                        'author':
                        author.username
                    }))
                message_txt = get_template('email/mp/new.txt').render(
                    Context({
                        'username':
                        part.username,
                        'url':
                        settings.SITE_URL + n_topic.get_absolute_url(),
                        'author':
                        author.username
                    }))

                msg = EmailMultiAlternatives(subject, message_txt, from_email,
                                             [part.email])
                msg.attach_alternative(message_html, "text/html")
                try:
                    msg.send()
                except:
                    msg = None
    if leave:
        move = n_topic.participants.first()
        n_topic.author = move
        n_topic.participants.remove(move)
        n_topic.save()

    return n_topic
Пример #41
0
def answer(request):
    """Adds an answer from an user to a topic."""
    try:
        topic_pk = request.GET["sujet"]
    except KeyError:
        raise Http404

    # Retrieve current topic.
    g_topic = get_object_or_404(PrivateTopic, pk=topic_pk)

    # Retrieve 3 last posts of the currenta topic.
    posts = PrivatePost.objects.filter(privatetopic=g_topic).order_by("-pubdate")[:3]
    last_post_pk = g_topic.last_message.pk

    # User would like preview his post or post a new post on the topic.
    if request.method == "POST":
        data = request.POST
        newpost = last_post_pk != int(data["last_post"])

        # Using the « preview button », the « more » button or new post
        if "preview" in data or newpost:
            form = PrivatePostForm(g_topic, request.user, initial={"text": data["text"]})
            return render_template(
                "mp/post/new.html", {"topic": g_topic, "last_post_pk": last_post_pk, "newpost": newpost, "form": form}
            )

        # Saving the message
        else:
            form = PrivatePostForm(g_topic, request.user, request.POST)
            if form.is_valid():
                data = form.data

                post = PrivatePost()
                post.privatetopic = g_topic
                post.author = request.user
                post.text = data["text"]
                post.text_html = emarkdown(data["text"])
                post.pubdate = datetime.now()
                post.position_in_topic = g_topic.get_post_count() + 1
                post.save()

                g_topic.last_message = post
                g_topic.save()

                # send email
                subject = "ZDS - MP : " + g_topic.title
                from_email = "Zeste de Savoir <{0}>".format(settings.MAIL_NOREPLY)
                parts = list(g_topic.participants.all())
                parts.append(g_topic.author)
                parts.remove(request.user)
                for part in parts:
                    profile = part.profile
                    if profile.email_for_answer:
                        pos = post.position_in_topic - 1
                        last_read = PrivateTopicRead.objects.filter(
                            privatetopic=g_topic, privatepost__position_in_topic=pos, user=part
                        ).count()
                        if last_read > 0:
                            message_html = get_template("email/mp/new.html").render(
                                Context(
                                    {
                                        "username": part.username,
                                        "url": settings.SITE_URL + post.get_absolute_url(),
                                        "author": request.user.username,
                                    }
                                )
                            )
                            message_txt = get_template("email/mp/new.txt").render(
                                Context(
                                    {
                                        "username": part.username,
                                        "url": settings.SITE_URL + post.get_absolute_url(),
                                        "author": request.user.username,
                                    }
                                )
                            )

                            msg = EmailMultiAlternatives(subject, message_txt, from_email, [part.email])
                            msg.attach_alternative(message_html, "text/html")
                            msg.send()

                return redirect(post.get_absolute_url())
            else:
                return render_template(
                    "mp/post/new.html",
                    {"topic": g_topic, "last_post_pk": last_post_pk, "newpost": newpost, "form": form},
                )

    else:
        text = ""

        # Using the quote button
        if "cite" in request.GET:
            post_cite_pk = request.GET["cite"]
            post_cite = PrivatePost.objects.get(pk=post_cite_pk)

            for line in post_cite.text.splitlines():
                text = text + "> " + line + "\n"

            text = u"{0}Source:[{1}]({2}{3})".format(
                text, post_cite.author.username, settings.SITE_URL, post_cite.get_absolute_url()
            )

        form = PrivatePostForm(g_topic, request.user, initial={"text": text})
        return render_template(
            "mp/post/new.html", {"topic": g_topic, "posts": posts, "last_post_pk": last_post_pk, "form": form}
        )
Пример #42
0
def answer(request):
    '''
    Adds an answer from a user to an article
    '''
    try:
        article_pk = request.GET['article']
    except KeyError:
        raise Http404
    
    g_article = get_object_or_404(Article, pk=article_pk)
    
    reactions = Reaction.objects.filter(article=g_article).order_by('-pubdate')[:3]
    
    if g_article.last_reaction:
        last_reaction_pk = g_article.last_reaction.pk
    else:
        last_reaction_pk=0

    # Making sure reactioning is allowed
    if g_article.is_locked:
        raise Http404

    # Check that the user isn't spamming
    if g_article.antispam(request.user):
        raise Http404

    # If we just sent data
    if request.method == 'POST':
        data = request.POST
        newreaction = last_reaction_pk != int(data['last_reaction'])

        # Using the « preview button », the « more » button or new reaction
        if 'preview' in data or 'more' in data or newreaction:
            return render_template('article/answer.html', {
                'text': data['text'], 'article': g_article, 'reactions': reactions,
                'last_reaction_pk': last_reaction_pk, 'newreaction': newreaction
            })

        # Saving the message
        else:
            form = ReactionForm(request.POST)
            if form.is_valid() and data['text'].strip() !='':
                data = form.data

                reaction = Reaction()
                reaction.article = g_article
                reaction.author = request.user
                reaction.text = data['text']
                reaction.text_html = emarkdown(data['text'])
                reaction.pubdate = datetime.now()
                reaction.position = g_article.get_reaction_count() + 1
                reaction.ip_address = get_client_ip(request)
                reaction.save()

                g_article.last_reaction = reaction
                g_article.save()

                return redirect(reaction.get_absolute_url())
            else:
                raise Http404

    else:
        text = ''

        # Using the quote button
        if 'cite' in request.GET:
            reaction_cite_pk = request.GET['cite']
            reaction_cite = Reaction.objects.get(pk=reaction_cite_pk)

            for line in reaction_cite.text.splitlines():
                text = text + '> ' + line + '\n'

            text = u'**{0} a écrit :**\n{1}\n'.format(
                reaction_cite.author.username, text)

        return render_template('article/answer.html', {
            'article': g_article, 'text': text, 'reactions': reactions,
            'last_reaction_pk': last_reaction_pk
        })
Пример #43
0
def publish_container(
    db_object,
    base_dir,
    container,
    template="tutorialv2/export/chapter.html",
    file_ext="html",
    image_callback=None,
    **ctx,
):
    """'Publish' a given container, in a recursive way
    Only here for epub publication (complexity of image/path traversal for the archive to be built)

    :param image_callback: callback used to change images tags on the created html
    :type image_callback: callable
    :param db_object: database representation of the content
    :type db_object: PublishableContent
    :param base_dir: directory of the top container
    :type base_dir: str
    :param template: the django template we will use to produce chapter export to html.
    :param container: a given container
    :type container: Container
    :param file_ext: output file extension
    :raise FailureDuringPublication: if anything goes wrong
    """

    from zds.tutorialv2.models.versioned import Container
    from zds.tutorialv2.publication_utils import FailureDuringPublication

    path_to_title_dict = collections.OrderedDict()
    ctx["relative"] = ctx.get("relative", ".")
    if not isinstance(container, Container):
        raise FailureDuringPublication(_("Le conteneur n'en est pas un !"))

    # jsFiddle support
    is_js = ""
    if db_object.js_support:
        is_js = "js"

    current_dir = path.dirname(
        path.join(base_dir, container.get_prod_path(relative=True)))

    if not path.isdir(current_dir):
        makedirs(current_dir)

    img_relative_path = ".." if ctx[
        "relative"] == "." else "../" + ctx["relative"]
    if container.has_extracts(
    ):  # the container can be rendered in one template
        wrapped_image_callback = image_callback(
            img_relative_path) if image_callback else image_callback
        args = {"container": container, "is_js": is_js}
        args.update(ctx)
        args["relative"] = img_relative_path
        parsed = render_to_string(template, args)
        write_chapter_file(
            base_dir,
            container,
            Path(container.get_prod_path(True, file_ext)),
            parsed,
            path_to_title_dict,
            wrapped_image_callback,
        )
        for extract in container.children:
            extract.text = None

        container.introduction = None
        container.conclusion = None

    else:  # separate render of introduction and conclusion
        wrapped_image_callback_intro_ccl = image_callback(
            img_relative_path) if image_callback else image_callback
        # create subdirectory
        if not path.isdir(current_dir):
            makedirs(current_dir)
        relative_ccl_path = "../" + ctx.get("relative", ".")
        if container.introduction and container.get_introduction():
            part_path = Path(container.get_prod_path(relative=True),
                             "introduction." + file_ext)
            args = {"text": container.get_introduction()}
            args.update(ctx)
            args["relative"] = relative_ccl_path
            if ctx.get("intro_ccl_template", None):
                parsed = render_to_string(ctx.get("intro_ccl_template"), args)
            else:
                parsed = emarkdown(container.get_introduction(),
                                   db_object.js_support)
            container.introduction = str(part_path)
            write_chapter_file(base_dir, container, part_path, parsed,
                               path_to_title_dict,
                               wrapped_image_callback_intro_ccl)
        children = copy.copy(container.children)
        container.children = []
        container.children_dict = {}
        for child in filter(lambda c: c.ready_to_publish, children):

            altered_version = copy.copy(child)
            container.children.append(altered_version)
            container.children_dict[altered_version.slug] = altered_version
            if not child.has_extracts():
                ctx["relative"] = "../" + ctx["relative"]
            result = publish_container(
                db_object,
                base_dir,
                altered_version,
                file_ext=file_ext,
                image_callback=image_callback,
                template=template,
                **ctx,
            )
            path_to_title_dict.update(result)
        if container.conclusion and container.get_conclusion():
            part_path = Path(container.get_prod_path(relative=True),
                             "conclusion." + file_ext)
            args = {"text": container.get_conclusion()}
            args.update(ctx)
            args["relative"] = relative_ccl_path
            if ctx.get("intro_ccl_template", None):
                parsed = render_to_string(ctx.get("intro_ccl_template"), args)
            else:
                parsed = emarkdown(container.get_conclusion(),
                                   db_object.js_support)
            container.conclusion = str(part_path)
            write_chapter_file(base_dir, container, part_path, parsed,
                               path_to_title_dict,
                               wrapped_image_callback_intro_ccl)

    return path_to_title_dict
Пример #44
0
def publish_container(db_object, base_dir, container):
    """ "Publish" a given container, in a recursive way

    :param db_object: database representation of the content
    :type db_object: PublishableContent
    :param base_dir: directory of the top container
    :type base_dir: str
    :param container: a given container
    :type container: Container
    :raise FailureDuringPublication: if anything goes wrong
    """

    from zds.tutorialv2.models.models_versioned import Container

    if not isinstance(container, Container):
        raise FailureDuringPublication(_(u'Le conteneur n\'en est pas un !'))

    template = 'tutorialv2/export/chapter.html'

    # jsFiddle support
    if db_object.js_support:
        is_js = "js"
    else:
        is_js = ""

    current_dir = os.path.dirname(
        os.path.join(base_dir, container.get_prod_path(relative=True)))

    if not os.path.isdir(current_dir):
        os.makedirs(current_dir)

    if container.has_extracts(
    ):  # the container can be rendered in one template
        parsed = render_to_string(template, {
            'container': container,
            'is_js': is_js
        })
        f = codecs.open(os.path.join(base_dir,
                                     container.get_prod_path(relative=True)),
                        'w',
                        encoding='utf-8')

        try:
            f.write(parsed)
        except (UnicodeError, UnicodeEncodeError):
            raise FailureDuringPublication(
                _(u'Une erreur est survenue durant la publication de « {} », vérifiez le code markdown'
                  ).format(container.title))

        f.close()

        for extract in container.children:
            extract.text = None

        container.introduction = None
        container.conclusion = None

    else:  # separate render of introduction and conclusion

        current_dir = os.path.join(
            base_dir,
            container.get_prod_path(relative=True))  # create subdirectory

        if not os.path.isdir(current_dir):
            os.makedirs(current_dir)

        if container.introduction:
            path = os.path.join(container.get_prod_path(relative=True),
                                'introduction.html')
            f = codecs.open(os.path.join(base_dir, path),
                            'w',
                            encoding='utf-8')

            try:
                f.write(
                    emarkdown(container.get_introduction(),
                              db_object.js_support))
            except (UnicodeError, UnicodeEncodeError):
                raise FailureDuringPublication(
                    _(u'Une erreur est survenue durant la publication de l\'introduction de « {} »,'
                      u' vérifiez le code markdown').format(container.title))

            container.introduction = path

        if container.conclusion:
            path = os.path.join(container.get_prod_path(relative=True),
                                'conclusion.html')
            f = codecs.open(os.path.join(base_dir, path),
                            'w',
                            encoding='utf-8')

            try:
                f.write(
                    emarkdown(container.get_conclusion(),
                              db_object.js_support))
            except (UnicodeError, UnicodeEncodeError):
                raise FailureDuringPublication(
                    _(u'Une erreur est survenue durant la publication de la conclusion de « {} »,'
                      u' vérifiez le code markdown').format(container.title))

            container.conclusion = path

        for child in container.children:
            publish_container(db_object, base_dir, child)
Пример #45
0
 def perform_update(self, instance, data):
     instance.text = data.get('text')
     instance.text_html = emarkdown(data.get('text'))
     instance.update = datetime.now()
     instance.save()
     return instance