68 lines
1.1 KiB
Go
68 lines
1.1 KiB
Go
package db
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type CooldownEntry struct {
|
|
UserID string
|
|
QuestionID string
|
|
}
|
|
|
|
type Cooldowns struct {
|
|
m map[CooldownEntry]time.Time
|
|
mu *sync.Mutex
|
|
}
|
|
|
|
func NewCooldowns() Cooldowns {
|
|
c := make(map[CooldownEntry]time.Time)
|
|
mu := &sync.Mutex{}
|
|
|
|
go func() {
|
|
for {
|
|
mu.Lock()
|
|
now := time.Now()
|
|
for k, v := range c {
|
|
if now.After(v) {
|
|
delete(c, k)
|
|
}
|
|
}
|
|
mu.Unlock()
|
|
time.Sleep(time.Minute * 5)
|
|
}
|
|
}()
|
|
return Cooldowns{c, mu}
|
|
}
|
|
|
|
func (c Cooldowns) NewAttempt(userID string, questionID string, attempts int) {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
var timeout time.Duration
|
|
switch attempts {
|
|
case 0:
|
|
timeout = time.Minute
|
|
case 1:
|
|
timeout = time.Minute * 3 / 2 // 90 seconds
|
|
case 2:
|
|
timeout = time.Minute * 3
|
|
default:
|
|
timeout = time.Minute * 5
|
|
}
|
|
|
|
c.m[CooldownEntry{userID, questionID}] = time.Now().Add(timeout)
|
|
}
|
|
|
|
func (c Cooldowns) Check(userID string, questionID string) time.Duration {
|
|
c.mu.Lock()
|
|
defer c.mu.Unlock()
|
|
expires, ok := c.m[CooldownEntry{userID, questionID}]
|
|
|
|
now := time.Now()
|
|
if !ok || now.After(expires) {
|
|
return 0
|
|
}
|
|
|
|
return expires.Sub(now)
|
|
}
|