justcaptcha/pkg/captcha/captcha.go

79 lines
1.5 KiB
Go
Raw Normal View History

package captcha
import (
"crypto/rand"
"image"
"math/big"
"time"
)
const (
maxIntAnswer = 999999
)
type Answer string
func NewIntAnswer() Answer {
ans, _ := rand.Int(rand.Reader, big.NewInt(maxIntAnswer))
return (Answer(ans.String()))
}
// Captcha interface that should be implemented by captcha.
type Captcha interface {
// Image generates and returns an image of captcha.
Image(style string) *image.Image
2022-06-27 00:43:12 +04:00
// GetAnswer returns a pregenerated answer.
Answer() Answer
2022-06-27 00:43:12 +04:00
// Solve compares a stored answer with a passed one.
// Sets field Solved to true if they are equal.
Solve(answer Answer) bool
2022-06-27 00:43:12 +04:00
// IsSolved returns field IsSolved.
IsSolved() bool
2022-06-27 00:43:12 +04:00
// Expiry returns a date after what captcha will expire.
Expiry() time.Time
}
// BaseCaptcha is a base implementation of a CAPTCHA.
2022-06-27 00:43:12 +04:00
//
// All derivatives that embed this struct only need to
// implement Image() method.
type BaseCaptcha struct {
answer Answer
solved bool
expireIn time.Time
}
func NewBaseCaptcha(expiry time.Duration) *BaseCaptcha {
return &BaseCaptcha{
expireIn: ExpiryDate(expiry),
}
}
func (c *BaseCaptcha) Image(style string) *image.Image {
return nil
}
func (c *BaseCaptcha) Answer() Answer {
if c.answer == "" {
c.answer = NewIntAnswer()
}
return c.answer
}
func (c *BaseCaptcha) Solve(answer Answer) bool {
c.solved = c.answer == answer
return c.solved
}
func (c *BaseCaptcha) IsSolved() bool {
return c.solved
}
func (c *BaseCaptcha) Expiry() time.Time {
return c.expireIn
}
func ExpiryDate(expiry time.Duration) time.Time {
return time.Now().Add(expiry)
}