79 lines
1.5 KiB
Go
79 lines
1.5 KiB
Go
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
|
|
// GetAnswer returns a pregenerated answer.
|
|
GetAnswer() Answer
|
|
// Solve compares a stored answer with a passed one.
|
|
// Sets field Solved to true if they are equal.
|
|
Solve(answer Answer) bool
|
|
// IsSolved returns field IsSolved.
|
|
IsSolved() bool
|
|
// Expiry returns a date after what captcha will expire.
|
|
Expiry() time.Time
|
|
}
|
|
|
|
// BaseCaptcha is a base implementation of a CAPTCHA.
|
|
//
|
|
// 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) GetAnswer() 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)
|
|
}
|