package handlers import ( "fmt" "image/jpeg" "justcaptcha/internal/dwcaptcha" "justcaptcha/pkg/captcha" "justcaptcha/pkg/captcha/inmemdb" "justcaptcha/pkg/server" "net/http" "time" ) const errMsgNotFound = "CAPTCHA with such ID doesn't exist" const errMsgWrongAnswer = "An answer provided was wrong" const errMsgFailedToGenImage = "failed to generate an image for a CAPTCHA" const errMsgImageNotFound = "cannot get an image for a non-existing CAPTCHA" type CaptchaHandlers struct { expiry time.Duration } func New(expiry time.Duration) *CaptchaHandlers { inmemdb.SetExpiry(expiry) return &CaptchaHandlers{expiry: expiry} } func (h *CaptchaHandlers) New(w http.ResponseWriter, r *http.Request) { dc := dwcaptcha.NewDwellingCaptcha(h.expiry) _, id := inmemdb.New(r.RemoteAddr, dc) w.WriteHeader(http.StatusCreated) fmt.Fprint(w, id) } func (h *CaptchaHandlers) Image(w http.ResponseWriter, r *http.Request) { captchaID := captcha.ID(server.GetURLParam(r, "captcha")) captchaStyle := r.URL.Query().Get("style") captchaImage, err := inmemdb.Image(captchaID, captchaStyle) if err != nil { w.WriteHeader(http.StatusNotFound) fmt.Fprint(w, errMsgImageNotFound) return } if captchaImage == nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, errMsgFailedToGenImage) return } w.Header().Add("Content-Disposition", "inline; filename=\""+string(captchaID)+"\"") jpeg.Encode(w, *captchaImage, &jpeg.Options{Quality: 20}) } func (h *CaptchaHandlers) Solve(w http.ResponseWriter, r *http.Request) { captchaID := captcha.ID(server.GetURLParam(r, "captcha")) r.ParseForm() answer := captcha.Answer(r.FormValue("answer")) ok, err := inmemdb.Solve(captchaID, answer) if err != nil { w.WriteHeader(http.StatusNotFound) fmt.Fprint(w, errMsgNotFound) return } if !ok { w.WriteHeader(http.StatusForbidden) fmt.Fprint(w, errMsgWrongAnswer) return } w.WriteHeader(http.StatusAccepted) } func (h *CaptchaHandlers) IsSolved(w http.ResponseWriter, r *http.Request) { captchaID := captcha.ID(server.GetURLParam(r, "captcha")) isJustRemove := r.URL.Query().Has("remove") w.WriteHeader(http.StatusNoContent) if isJustRemove { inmemdb.Remove(captchaID) return } solved, err := inmemdb.IsSolved(captchaID) if err != nil { w.WriteHeader(http.StatusNotFound) fmt.Fprint(w, errMsgNotFound) return } if !solved { w.WriteHeader(http.StatusForbidden) fmt.Fprint(w, errMsgWrongAnswer) } }