website/pkg/controller/poll/vote.go
Noah Petherbridge 1cc2306cbf Wrap Up Polls Support
* Add the PollVotes table and associated logic.
* Multiple choice polls supported.
* Expiring and non-expiring polls.
* Icons and badges on the forum pages to show posts with polls
* Bugfix: non-explicit users getting SQL errors on Newest Posts page.
2022-12-20 19:15:45 -08:00

92 lines
2.3 KiB
Go

package poll
import (
"fmt"
"net/http"
"strconv"
"code.nonshy.com/nonshy/website/pkg/models"
"code.nonshy.com/nonshy/website/pkg/session"
"code.nonshy.com/nonshy/website/pkg/templates"
)
// Vote controller for polls.
func Vote() http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var (
// Form parameters
pollID uint64
fromThreadID uint64
answers = r.Form["answer"] // a slice in case of MultipleChoice
nextURL string
)
// Parse integer params.
if value, err := strconv.Atoi(r.FormValue("poll_id")); err != nil {
session.FlashError(w, r, "Invalid poll ID")
templates.Redirect(w, "/")
return
} else {
pollID = uint64(value)
}
// Currently polls only exist in forum threads, require the thread ID.
if value, err := strconv.Atoi(r.FormValue("from_thread_id")); err != nil {
session.FlashError(w, r, "Invalid thread ID")
templates.Redirect(w, "/")
return
} else {
fromThreadID = uint64(value)
nextURL = fmt.Sprintf("/forum/thread/%d", fromThreadID)
}
// POST request only.
if r.Method != http.MethodPost {
session.FlashError(w, r, "POST requests only.")
templates.Redirect(w, nextURL)
return
}
// An answer is required.
if len(answers) == 0 || len(answers) == 1 && answers[0] == "" {
session.FlashError(w, r, "An answer to this poll is required for voting.")
templates.Redirect(w, nextURL)
return
}
// Get the current user.
user, err := session.CurrentUser(r)
if err != nil {
session.FlashError(w, r, "Unexpected error: couldn't get CurrentUser")
templates.Redirect(w, nextURL)
return
}
// Look up the poll.
poll, err := models.GetPoll(pollID)
if err != nil {
session.FlashError(w, r, "Poll not found.")
templates.Redirect(w, nextURL)
return
}
// Is it accepting responses?
result := poll.Result(user)
if !result.AcceptingVotes {
session.FlashError(w, r, "This poll is not accepting your vote at this time.")
templates.Redirect(w, nextURL)
return
}
// Cast the vote!
if err := poll.CastVote(user, answers); err != nil {
session.FlashError(w, r, "Couldn't cast the vote: %s", err)
templates.Redirect(w, nextURL)
return
}
session.Flash(w, r, "Your vote has been recorded!")
templates.Redirect(w, nextURL)
})
}