2022-06-24 23:09:46 +04:00
|
|
|
package captcha
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/rand"
|
|
|
|
"image"
|
|
|
|
"math/big"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/fogleman/gg"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
dwImageWidth = 160
|
|
|
|
dwImageHeight = 40
|
|
|
|
)
|
|
|
|
|
|
|
|
type DwellingCaptcha struct {
|
|
|
|
Captcha
|
|
|
|
}
|
|
|
|
|
2022-06-26 20:51:04 +04:00
|
|
|
func NewDwellingCaptcha(expiry time.Duration) *DwellingCaptcha {
|
2022-06-24 23:09:46 +04:00
|
|
|
return &DwellingCaptcha{
|
|
|
|
Captcha: Captcha{
|
|
|
|
Answer: GenerateAnswer(),
|
2022-06-26 20:51:04 +04:00
|
|
|
ExpireIn: ExpiryDate(expiry)}}
|
2022-06-24 23:09:46 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *DwellingCaptcha) GenerateImage() *image.Image {
|
|
|
|
ctx := gg.NewContext(dwImageWidth, dwImageHeight)
|
|
|
|
|
|
|
|
// fill background
|
|
|
|
ctx.SetRGB255(0x0a, 0x0a, 0x0a)
|
|
|
|
ctx.Clear()
|
|
|
|
|
|
|
|
// draw text
|
|
|
|
ctx.SetRGB255(0xf5, 0xf5, 0xf5)
|
|
|
|
ctx.Scale(4.0, 2.7)
|
|
|
|
ctx.DrawStringAnchored(string(c.GetAnswer()), 20, 5, .5, .5)
|
|
|
|
|
|
|
|
// draw lines and points
|
|
|
|
|
|
|
|
ctx.SetRGB255(0x9f, 0x2b, 0x68)
|
|
|
|
for i := 0; i < 16; i++ {
|
|
|
|
x0, _ := rand.Int(rand.Reader, big.NewInt(int64(ctx.Height())))
|
|
|
|
x1, _ := rand.Int(rand.Reader, big.NewInt(int64(ctx.Height())))
|
|
|
|
ctx.SetLineWidth(2)
|
|
|
|
r, _ := rand.Int(rand.Reader, big.NewInt(int64(4)))
|
|
|
|
ctx.DrawPoint(float64(x0.Int64()), float64(x1.Int64()), float64(r.Int64()))
|
|
|
|
ctx.DrawLine(float64(x0.Int64()), 0, float64(ctx.Height()), float64(x1.Int64()))
|
|
|
|
ctx.Stroke()
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < 16; i++ {
|
|
|
|
x0, _ := rand.Int(rand.Reader, big.NewInt(int64(ctx.Height())))
|
|
|
|
x1, _ := rand.Int(rand.Reader, big.NewInt(int64(ctx.Height())))
|
|
|
|
ctx.SetLineWidth(2)
|
|
|
|
ctx.DrawLine(0, float64(x0.Int64()), float64(x1.Int64()), float64(ctx.Height()))
|
|
|
|
r, _ := rand.Int(rand.Reader, big.NewInt(int64(4)))
|
|
|
|
ctx.DrawPoint(float64(x0.Int64()), float64(x1.Int64()), float64(r.Int64()))
|
|
|
|
ctx.Stroke()
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Image = ctx.Image()
|
|
|
|
|
|
|
|
return &c.Image
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *DwellingCaptcha) GetImage() *image.Image {
|
|
|
|
if c.Image == nil {
|
|
|
|
return c.GenerateImage()
|
|
|
|
}
|
|
|
|
|
|
|
|
return &c.Image
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *DwellingCaptcha) Solve(answer Answer) bool {
|
|
|
|
c.Solved = c.Answer == answer
|
|
|
|
return c.Solved
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *DwellingCaptcha) GetAnswer() Answer {
|
|
|
|
return c.Answer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *DwellingCaptcha) IsSolved() bool {
|
|
|
|
return c.Solved
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *DwellingCaptcha) Expire() time.Time {
|
|
|
|
return c.ExpireIn
|
|
|
|
}
|