Beispiel #1
0
def edit_poll(request, author, permlink):
    if not request.user.is_authenticated:
        return redirect('login')

    try:
        poll = Question.objects.get(
            permlink=permlink,
            username=author,
        )
    except Question.DoesNotExist:
        raise Http404

    if author != request.user.username:
        raise Http404

    if request.method == "GET":
        poll_data = fetch_poll_data(poll.username, poll.permlink)
        tags = poll_data.get("tags", [])
        tags = [tag for tag in tags if tag not in settings.DEFAULT_TAGS]
        form_data = {
            "question": poll.text,
            "description": poll.description,
            "answers": [c.text for c in Choice.objects.filter(question=poll)],
            "expire_at": poll.expire_at_humanized,
            "tags": ",".join(tags),
            "allow_multiple_choices": poll.allow_multiple_choices
        }

    if request.method == 'POST':
        form_data = copy.copy(request.POST)

        if 'sc_token' not in request.session:
            return redirect("/")

        error, question, choices, expire_at, _, days, tags, \
            allow_multiple_choices = validate_input(request)
        if tags:
            tags = settings.DEFAULT_TAGS + tags
        else:
            tags = settings.DEFAULT_TAGS

        permlink = poll.permlink

        if error:
            form_data.update({
                "answers":
                request.POST.getlist("answers[]"),
                "expire_at":
                request.POST.get("expire-at"),
                "allow_multiple_choices":
                request.POST.get("allow-multiple-choices"),
            })
            return render(request, "edit.html", {"form_data": form_data})

        # add question
        question = add_or_get_question(request, question, permlink, days,
                                       allow_multiple_choices)
        question.save()

        # add answers attached to it
        add_choices(question, choices, flush=True)

        # send it to the steem blockchain
        sc_client = Client(access_token=request.session.get("sc_token"),
                           oauth_base_url="https://hivesigner.com/oauth2/",
                           sc2_api_base_url="https://hivesigner.com/api/")
        comment = get_comment(request, question, choices, permlink, tags=tags)
        if not settings.BROADCAST_TO_BLOCKCHAIN:
            resp = {}
        else:
            resp = sc_client.broadcast([
                comment.to_operation_structure(),
            ])

        if 'error' in resp:
            if 'The token has invalid role' in resp.get("error_description"):
                # expired token
                auth_logout(request)
                return redirect('login')

            messages.add_message(request, messages.ERROR,
                                 resp.get("error_description", "error"))
            question.delete()
            return redirect('edit', args=(author, permlink))

        return redirect('detail', question.username, question.permlink)

    return render(request, "edit.html", {
        "form_data": form_data,
    })
Beispiel #2
0
def vote(request, user, permlink):
    if request.method != "POST":
        raise Http404

    # django admin users should not be able to vote.
    if not request.session.get("sc_token"):
        redirect('logout')

    try:
        poll = Question.objects.get(username=user, permlink=permlink)
    except Question.DoesNotExist:
        raise Http404

    if not request.user.is_authenticated:
        return redirect('login')

    if poll.allow_multiple_choices:
        choice_ids = request.POST.getlist("choice-id")
    else:
        choice_ids = [
            request.POST.get("choice-id"),
        ]

    # remove noise
    choice_ids = [x for x in choice_ids if x is not None]

    additional_thoughts = request.POST.get("vote-comment", "")

    if not len(choice_ids):
        messages.add_message(request, messages.ERROR,
                             "You need to pick a choice to vote.")
        return redirect("detail", poll.username, poll.permlink)

    if Choice.objects.filter(voted_users__username=request.user,
                             question=poll).exists():
        messages.add_message(request, messages.ERROR,
                             "You have already voted for this poll!")

        return redirect("detail", poll.username, poll.permlink)

    if not poll.is_votable():
        messages.add_message(request, messages.ERROR, "This poll is expired!")
        return redirect("detail", poll.username, poll.permlink)

    for choice_id in choice_ids:
        try:
            choice = Choice.objects.get(pk=int(choice_id))
        except Choice.DoesNotExist:
            raise Http404

    choice_instances = []
    for choice_id in choice_ids:
        choice = Choice.objects.get(pk=int(choice_id))
        choice_instances.append(choice)

    # send it to the steem blockchain
    sc_client = Client(access_token=request.session.get("sc_token"),
                       oauth_base_url="https://hivesigner.com/oauth2/",
                       sc2_api_base_url="https://hivesigner.com/api/")

    choice_text = ""
    for c in choice_instances:
        choice_text += f" - {c.text.strip()}\n"

    body = f"Voted for \n {choice_text}"
    if additional_thoughts:
        body += f"\n\n{additional_thoughts}"
    comment = Comment(author=request.user.username,
                      permlink=str(uuid.uuid4()),
                      body=body,
                      parent_author=poll.username,
                      parent_permlink=poll.permlink,
                      json_metadata={
                          "tags": settings.DEFAULT_TAGS,
                          "app": f"dpoll/{settings.DPOLL_APP_VERSION}",
                          "content_type": "poll_vote",
                          "votes": [c.text.strip() for c in choice_instances],
                      })

    comment_options = get_comment_options(comment)
    if not settings.BROADCAST_TO_BLOCKCHAIN:
        resp = {}
    else:
        resp = sc_client.broadcast([
            comment.to_operation_structure(),
            comment_options.to_operation_structure(),
        ])

    # Steemconnect sometimes returns 503.
    # https://github.com/steemscript/steemconnect/issues/356
    if not isinstance(resp, dict):
        messages.add_message(
            request, messages.ERROR,
            "We got an unexpected error from Steemconnect. Please, try again.")
        return redirect("detail", poll.username, poll.permlink)

    # Expected way to receive errors on broadcasting
    if 'error' in resp:
        messages.add_message(request, messages.ERROR,
                             resp.get("error_description", "error"))

        return redirect("detail", poll.username, poll.permlink)

    # register the vote to the database
    for choice_instance in choice_instances:
        choice_instance.voted_users.add(request.user)

    block_id = resp.get("result", {}).get("block_num")
    trx_id = resp.get("result", {}).get("id")

    # add trx id and block id to the audit log
    vote_audit = VoteAudit(question=poll,
                           voter=request.user,
                           block_id=block_id,
                           trx_id=trx_id)
    vote_audit.save()
    for choice_instance in choice_instances:
        vote_audit.choices.add(choice_instance)

    messages.add_message(request, messages.SUCCESS,
                         "You have successfully voted!")

    return redirect("detail", poll.username, poll.permlink)
Beispiel #3
0
def create_poll(request):
    if not request.user.is_authenticated:
        return redirect('login')

    if request.method == 'POST':
        form_data = copy.copy(request.POST)

        if 'sc_token' not in request.session:
            return redirect("/")

        error, question, choices, expire_at, permlink, days, tags, \
            allow_multiple_choices = validate_input(request)

        if error:
            form_data.update({
                "answers":
                request.POST.getlist("answers[]"),
                "expire_at":
                request.POST.get("expire-at"),
                "reward_option":
                request.POST.get("reward-option"),
                "allow_multiple_choices":
                request.POST.get("allow-multiple-choices"),
            })
            return render(request, "add.html", {"form_data": form_data})

        if (Question.objects.filter(permlink=permlink,
                                    username=request.user)).exists():
            messages.add_message(request, messages.ERROR,
                                 "You have already a similar poll.")
            return redirect('create-poll')

        # add question
        question = add_or_get_question(request, question, permlink, days,
                                       allow_multiple_choices)
        question.save()

        # add answers attached to it
        add_choices(question, choices)

        # send it to the steem blockchain
        sc_client = Client(access_token=request.session.get("sc_token"),
                           oauth_base_url="https://hivesigner.com/oauth2/",
                           sc2_api_base_url="https://hivesigner.com/api/")
        comment = get_comment(request, question, choices, permlink, tags)
        comment_options = get_comment_options(
            comment, reward_option=request.POST.get("reward-option"))
        if not settings.BROADCAST_TO_BLOCKCHAIN:
            resp = {}
        else:
            resp = sc_client.broadcast([
                comment.to_operation_structure(),
                comment_options.to_operation_structure(),
            ])

        if 'error' in resp:
            if 'The token has invalid role' in resp.get("error_description"):
                # expired token
                auth_logout(request)
                return redirect('login')

            messages.add_message(request, messages.ERROR,
                                 resp.get("error_description", "error"))
            question.delete()
            return redirect('create-poll')

        return redirect('detail', question.username, question.permlink)

    return render(request, "add.html")