package anidb
import (
+ "encoding/gob"
"github.com/Kovensky/go-anidb/udp"
- "sync"
"time"
)
-var banTime time.Time
-var banTimeLock sync.Mutex
+func init() {
+ gob.RegisterName("*github.com/Kovensky/go-anidb.banCache", &banCache{})
+}
const banDuration = 30*time.Minute + 1*time.Second
+type banCache struct{ time.Time }
+
+func (c *banCache) Touch() {
+ c.Time = time.Now()
+}
+func (c *banCache) IsStale() bool {
+ return time.Now().Sub(c.Time) > banDuration
+}
+
// Returns whether the last UDP API access returned a 555 BANNED message.
func Banned() bool {
- banTimeLock.Lock()
- banTimeLock.Unlock()
+ var banTime banCache
+ cache.Get(&banTime, "banned")
- return _banned()
+ stale := banTime.IsStale()
+ if stale {
+ cache.Delete("banned")
+ }
+ return !stale
}
-func _banned() bool {
- return time.Now().Sub(banTime) > banDuration
+func setBanned() {
+ cache.Set(&banCache{}, "banned")
}
type paramSet struct {
type paramMap udpapi.ParamMap // shortcut
+type noauthAPIReply struct {
+ udpapi.APIReply
+}
+
+func (r *noauthAPIReply) Code() int {
+ return 501
+}
+
+func (r *noauthAPIReply) Text() string {
+ return "LOGIN FIRST"
+}
+
+func (r *noauthAPIReply) Error() error {
+ return &udpapi.APIError{Code: r.Code(), Desc: r.Text()}
+}
+
type bannedAPIReply struct {
udpapi.APIReply
}
return "BANNED"
}
func (r *bannedAPIReply) Error() error {
- return &udpapi.APIError{Code: 555, Desc: "BANNED"}
+ return &udpapi.APIError{Code: r.Code(), Desc: r.Text()}
}
var bannedReply udpapi.APIReply = &bannedAPIReply{}
case 503, 504: // client library rejected
panic(reply.Error())
case 555: // IP (and user, possibly client) temporarily banned
- banTimeLock.Lock()
-
- banTime = time.Now()
-
- banTimeLock.Unlock()
+ setBanned()
}
set.ch <- reply
close(set.ch)
func (udp *udpWrap) SendRecv(cmd string, params paramMap) <-chan udpapi.APIReply {
ch := make(chan udpapi.APIReply, 1)
+ if udp.credentials == nil {
+ ch <- &noauthAPIReply{}
+ close(ch)
+ return ch
+ }
- banTimeLock.Lock()
- defer banTimeLock.Unlock()
- if _banned() {
- banTime = time.Time{}
- } else {
+ if Banned() {
ch <- bannedReply
close(ch)
return ch