예제 #1
0
파일: posts.py 프로젝트: tibik/vas3k.club
def edit_post(request, post_slug):
    post = get_object_or_404(Post, slug=post_slug)
    if post.author != request.me and not request.me.is_moderator:
        raise AccessDenied()

    PostFormClass = POST_TYPE_MAP.get(post.type) or PostTextForm

    if request.method == "POST":
        form = PostFormClass(request.POST, request.FILES, instance=post)
        if form.is_valid():
            post = form.save(commit=False)
            if not post.author:
                post.author = request.me
            post.html = None  # flush cache
            post.save()

            SearchIndex.update_post_index(post)
            LinkedPost.create_links_from_text(post, post.text)

            if post.is_visible:
                return redirect("show_post", post.type, post.slug)
            else:
                return redirect("compose")
    else:
        form = PostFormClass(instance=post)

    return render(request, f"posts/compose/{post.type}.html", {
        "mode": "edit",
        "form": form
    })
예제 #2
0
def create_or_edit(request, post_type, post=None, mode="create"):
    FormClass = POST_TYPE_MAP.get(post_type) or PostTextForm

    # show blank form on GET
    if request.method != "POST":
        form = FormClass(instance=post)
        return render(request, f"posts/compose/{post_type}.html", {
            "mode": mode,
            "post_type": post_type,
            "form": form,
        })

    # validate form on POST
    form = FormClass(request.POST, request.FILES, instance=post)
    if form.is_valid():
        if not request.me.is_moderator:
            if Post.check_duplicate(user=request.me,
                                    title=form.cleaned_data["title"],
                                    ignore_post_id=post.id if post else None):
                raise ContentDuplicated()

            is_ok = Post.check_rate_limits(request.me)
            if not is_ok:
                raise RateLimitException(
                    title="🙅‍♂️ Слишком много постов",
                    message=
                    "В последнее время вы создали слишком много постов. Потерпите, пожалуйста."
                )

        post = form.save(commit=False)
        if not post.author_id:
            post.author = request.me
        post.type = post_type
        post.html = None  # flush cache
        post.save()

        if mode == "create" or not post.is_visible:
            PostSubscription.subscribe(request.me,
                                       post,
                                       type=PostSubscription.TYPE_ALL_COMMENTS)

        if post.is_visible:
            if post.topic:
                post.topic.update_last_activity()

            SearchIndex.update_post_index(post)
            LinkedPost.create_links_from_text(post, post.text)

        action = request.POST.get("action")
        if action == "publish":
            post.publish()
            LinkedPost.create_links_from_text(post, post.text)

        return redirect("show_post", post.type, post.slug)

    return render(request, f"posts/compose/{post_type}.html", {
        "mode": mode,
        "post_type": post_type,
        "form": form,
    })
예제 #3
0
def do_post_admin_actions(request, post, data):
    if not request.me.is_moderator:
        raise AccessDenied()

    do_common_admin_and_curator_actions(request, post, data)

    # Close comments
    if data["close_comments"]:
        post.is_commentable = False
        post.save()

    # Transfer ownership to the given username
    if data["transfer_ownership"]:
        user = User.objects.filter(
            slug=data["transfer_ownership"].strip()).first()
        if user:
            post.author = user
            post.save()

    if data["refresh_linked"]:
        LinkedPost.create_links_from_text(post, post.text)
        post_comments = Comment.visible_objects().filter(post=post,
                                                         is_deleted=False)
        for comment in post_comments:
            LinkedPost.create_links_from_text(comment.post, comment.text)

    return redirect("show_post", post.type, post.slug)
예제 #4
0
def create_comment(request, post_slug):
    post = get_object_or_404(Post, slug=post_slug)
    if not post.is_commentable and not request.me.is_moderator:
        raise AccessDenied(title="Комментарии к этому посту закрыты")

    if request.POST.get("reply_to_id"):
        ProperCommentForm = ReplyForm
    elif post.type == Post.TYPE_BATTLE:
        ProperCommentForm = BattleCommentForm
    else:
        ProperCommentForm = CommentForm

    if request.method == "POST":
        form = ProperCommentForm(request.POST)
        if form.is_valid():
            is_ok = Comment.check_rate_limits(request.me)
            if not is_ok:
                raise RateLimitException(
                    title="🙅‍♂️ Вы комментируете слишком часто",
                    message=
                    "Подождите немного, вы достигли нашего лимита на комментарии в день. "
                    "Можете написать нам в саппорт, пожаловаться об этом.")

            comment = form.save(commit=False)
            comment.post = post
            if not comment.author:
                comment.author = request.me

            comment.ipaddress = parse_ip_address(request)
            comment.useragent = parse_useragent(request)
            comment.save()

            # update the shitload of counters :)
            request.me.update_last_activity()
            Comment.update_post_counters(post)
            PostView.increment_unread_comments(comment)
            PostView.register_view(
                request=request,
                user=request.me,
                post=post,
            )
            SearchIndex.update_comment_index(comment)
            LinkedPost.create_links_from_text(post, comment.text)

            return redirect("show_comment", post.slug, comment.id)
        else:
            log.error(f"Comment form error: {form.errors}")
            return render(
                request, "error.html", {
                    "title": "Какая-то ошибка при публикации комментария 🤷‍♂️",
                    "message": f"Мы уже получили оповещение и скоро пофиксим. "
                    f"Ваш коммент мы сохранили чтобы вы могли скопировать его и запостить еще раз:",
                    "data": form.cleaned_data.get("text")
                })

    raise Http404()
예제 #5
0
def comment_to_post(update: Update, context: CallbackContext) -> None:
    user = get_club_user(update)
    if not user:
        return None

    post = get_club_post(update)
    if not post or post.type in [Post.TYPE_BATTLE, Post.TYPE_WEEKLY_DIGEST]:
        return None

    is_ok = Comment.check_rate_limits(user)
    if not is_ok:
        update.message.reply_text(
            f"🙅‍♂️ Извините, вы комментировали слишком часто и достигли дневного лимита"
        )
        return None

    text = update.message.text or update.message.caption
    if not text:
        update.message.reply_text(
            f"😣 Сорян, я пока умею только в текстовые реплаи"
        )
        return None

    if len(text) < MIN_COMMENT_LEN:
        update.message.reply_text(
            f"😋 Твой коммент слишком короткий. Не буду постить его в Клуб, пускай остается в чате"
        )
        return None

    reply = Comment.objects.create(
        author=user,
        post=post,
        text=text,
        useragent="TelegramBot (like TwitterBot)",
        metadata={
            "telegram": update.to_dict()
        }
    )
    LinkedPost.create_links_from_text(post, text)

    new_comment_url = settings.APP_HOST + reverse("show_comment", kwargs={
        "post_slug": reply.post.slug,
        "comment_id": reply.id
    })

    update.message.reply_text(
        f"➜ <a href=\"{new_comment_url}\">Отвечено</a> 👍",
        parse_mode=ParseMode.HTML,
        disable_web_page_preview=True
    )
예제 #6
0
def compose_type(request, post_type):
    if post_type not in dict(Post.TYPES):
        raise Http404()

    FormClass = POST_TYPE_MAP.get(post_type) or PostTextForm

    if request.method == "POST":
        form = FormClass(request.POST, request.FILES)
        if form.is_valid():

            if not request.me.is_moderator:
                if Post.check_duplicate(user=request.me,
                                        title=form.cleaned_data["title"]):
                    raise ContentDuplicated()

                is_ok = Post.check_rate_limits(request.me)
                if not is_ok:
                    raise RateLimitException(
                        title="🙅‍♂️ Слишком много постов",
                        message=
                        "В последнее время вы создали слишком много постов. Потерпите, пожалуйста."
                    )

            post = form.save(commit=False)
            post.author = request.me
            post.type = post_type
            post.save()

            PostSubscription.subscribe(request.me, post)

            if post.is_visible:
                if post.topic:
                    post.topic.update_last_activity()

                SearchIndex.update_post_index(post)
                LinkedPost.create_links_from_text(post, post.text)

            if post.is_visible or request.POST.get("show_preview"):
                return redirect("show_post", post.type, post.slug)
            else:
                return redirect("compose")
    else:
        form = FormClass()

    return render(request, f"posts/compose/{post_type}.html", {
        "mode": "create",
        "form": form
    })
예제 #7
0
    def handle(self, *args, **options):
        LinkedPost.objects.all().delete()

        posts = Post.visible_objects().exclude(
            type__in=[Post.TYPE_INTRO, Post.TYPE_WEEKLY_DIGEST])
        for post in posts:
            print(f"Parsing post: {post.slug}")
            LinkedPost.create_links_from_text(post, post.text)

        del posts

        comments = Comment.visible_objects()
        for comment in comments:
            print(f"Parsing comment: {comment.id}")
            LinkedPost.create_links_from_text(comment.post, comment.text)

        print("Done 🥙")
예제 #8
0
파일: posts.py 프로젝트: tibik/vas3k.club
def show_post(request, post_type, post_slug):
    post = get_object_or_404(Post, slug=post_slug)

    # post_type can be changed by moderator
    if post.type != post_type:
        return redirect("show_post", post.type, post.slug)

    # don't show private posts into public
    if not post.is_public:
        access_denied = check_user_permissions(request, post=post)
        if access_denied:
            return access_denied

    # drafts are visible only to authors and moderators
    if not post.is_visible:
        if not request.me or (request.me != post.author
                              and not request.me.is_moderator):
            raise Http404()

    # record a new view
    last_view_at = None
    if request.me:
        request.me.update_last_activity()
        post_view, last_view_at = PostView.register_view(
            request=request,
            user=request.me,
            post=post,
        )
    else:
        PostView.register_anonymous_view(
            request=request,
            post=post,
        )

    # find linked posts and sort them by upvotes
    linked_posts = sorted(
        {
            link.post_to if link.post_to != post else link.post_from
            for link in LinkedPost.links_for_post(post)[:50]
        },
        key=lambda p: p.upvotes,
        reverse=True)

    # force cleanup deleted/hidden posts from linked
    linked_posts = [p for p in linked_posts if p.is_visible]

    return render_post(request, post, {
        "post_last_view_at": last_view_at,
        "linked_posts": linked_posts,
    })