コード例 #1
0
    def create_user_badge(cls, badge, from_user, to_user, post=None, comment=None, note=None):
        if from_user == to_user:
            raise BadRequest(
                title="🛑 Нельзя дарить награды самому себе",
                message="Это что такое-то вообще!"
            )

        if badge.price_days >= from_user.membership_days_left():
            raise InsufficientFunds(
                title="💸 Недостаточно средств :(",
                message=f"Вы не можете подарить юзеру эту награду, "
                        f"так как у вас осталось {math.floor(from_user.membership_days_left())} дней членства, "
                        f"а награда стоит {badge.price_days}. "
                        f"Продлите членство в настройках своего профиля."
            )

        with transaction.atomic():
            # save user badge into the database
            try:
                user_badge = UserBadge.objects.create(
                    badge=badge,
                    from_user=from_user,
                    to_user=to_user,
                    post=post,
                    comment=comment,
                    note=note,
                )
            except IntegrityError:
                raise ContentDuplicated(
                    title="🛑 Вы уже дарили награду за этот пост или комментарий",
                    message="Повторно награды дарить нельзя. Но вы можете подарить другую награду."
                )

            # deduct days balance from profile
            User.objects\
                .filter(id=from_user.id)\
                .update(
                    membership_expires_at=F("membership_expires_at") - timedelta(days=badge.price_days)
                )

            # add badge to post/comment metadata (for caching purposes)
            comment_or_post = comment or post
            metadata = comment_or_post.metadata or {}
            badges = metadata.get("badges") or {}
            if badge.code not in badges:
                # add new badge
                badges[badge.code] = {
                    "title": badge.title,
                    "description": badge.description,
                    "count": 1,
                }
            else:
                # if badge exists, increment badge count
                badges[badge.code]["count"] += 1

            # update metadata only (do not use .save(), it saves all fields and can cause side-effects)
            metadata["badges"] = badges
            type(comment_or_post).objects.filter(id=comment_or_post.id).update(metadata=metadata)

        return user_badge
コード例 #2
0
ファイル: posts.py プロジェクト: thelebster/vas3k.club
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 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
    })