2022-06-24 23:09:46 +04:00
|
|
|
package captcha
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rand"
|
2022-06-26 23:24:10 +04:00
|
|
|
"errors"
|
2022-06-24 23:09:46 +04:00
|
|
|
"image"
|
|
|
|
"math/big"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
maxAnswer = 999999
|
|
|
|
)
|
|
|
|
|
|
|
|
var errorNotFound = errors.New("captcha not found")
|
|
|
|
|
|
|
|
type Answer string
|
|
|
|
|
2022-06-27 00:43:12 +04:00
|
|
|
// ICaptcha interface that should be implemented by captcha.
|
2022-06-24 23:09:46 +04:00
|
|
|
type ICaptcha interface {
|
2022-06-27 00:43:12 +04:00
|
|
|
// generateImage is used to create a captcha image.
|
2022-06-27 01:20:36 +04:00
|
|
|
generateImage(style string) *image.Image
|
2022-06-27 00:43:12 +04:00
|
|
|
// GetImage() returns an image of captcha. Calls
|
|
|
|
// generateImage() method if image doesn't exist.
|
2022-06-27 01:20:36 +04:00
|
|
|
GetImage(style string) *image.Image
|
2022-06-27 00:43:12 +04:00
|
|
|
// GetAnswer returns a pregenerated answer.
|
2022-06-24 23:09:46 +04:00
|
|
|
GetAnswer() 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.
|
2022-06-24 23:09:46 +04:00
|
|
|
Solve(answer Answer) bool
|
2022-06-27 00:43:12 +04:00
|
|
|
// IsSolved returns field IsSolved.
|
2022-06-24 23:09:46 +04:00
|
|
|
IsSolved() bool
|
2022-06-27 00:43:12 +04:00
|
|
|
// Expiry returns a date after what captcha will expire.
|
2022-06-26 20:47:25 +04:00
|
|
|
Expiry() time.Time
|
2022-06-24 23:09:46 +04:00
|
|
|
}
|
|
|
|
|
2022-06-27 00:43:12 +04:00
|
|
|
// Captcha is a base implementation of a CAPTCHA.
|
|
|
|
//
|
|
|
|
// All derivatives that embed this struct only need to
|
|
|
|
// implement GetImage() and generateImage() methods.
|
|
|
|
// And GetImage() could simply be copied.
|
|
|
|
//
|
|
|
|
// You need to do that because in Go there is no inheritance,
|
|
|
|
// and if you won't do that, calling a base GetImage
|
|
|
|
// method will call an empty base generateImage() method.
|
2022-06-24 23:09:46 +04:00
|
|
|
type Captcha struct {
|
|
|
|
Image image.Image
|
|
|
|
Answer Answer
|
|
|
|
Solved bool
|
|
|
|
ExpireIn time.Time
|
|
|
|
}
|
|
|
|
|
2022-06-27 01:20:36 +04:00
|
|
|
func (c *Captcha) generateImage(style string) *image.Image {
|
2022-06-26 23:53:52 +04:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-06-27 01:20:36 +04:00
|
|
|
func (c *Captcha) GetImage(style string) *image.Image {
|
2022-06-26 23:53:52 +04:00
|
|
|
if c.Image == nil {
|
2022-06-27 01:20:36 +04:00
|
|
|
return c.generateImage(style)
|
2022-06-26 23:53:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return &c.Image
|
|
|
|
}
|
|
|
|
|
2022-06-26 22:02:38 +04:00
|
|
|
func (c *Captcha) Solve(answer Answer) bool {
|
|
|
|
c.Solved = c.Answer == answer
|
|
|
|
return c.Solved
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Captcha) GetAnswer() Answer {
|
2022-06-27 00:44:11 +04:00
|
|
|
if c.Answer == "" {
|
|
|
|
c.Answer = generateAnswer()
|
|
|
|
}
|
2022-06-26 22:02:38 +04:00
|
|
|
return c.Answer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Captcha) IsSolved() bool {
|
|
|
|
return c.Solved
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Captcha) Expiry() time.Time {
|
|
|
|
return c.ExpireIn
|
|
|
|
}
|
|
|
|
|
2022-06-27 00:44:11 +04:00
|
|
|
func generateAnswer() Answer {
|
2022-06-24 23:09:46 +04:00
|
|
|
ans, _ := rand.Int(rand.Reader, big.NewInt(maxAnswer))
|
|
|
|
return (Answer(ans.String()))
|
|
|
|
}
|
|
|
|
|
2022-06-26 20:47:25 +04:00
|
|
|
func ExpiryDate(expiry time.Duration) time.Time {
|
|
|
|
return time.Now().Add(expiry)
|
2022-06-24 23:09:46 +04:00
|
|
|
}
|