Files
Cyrene_v2/plugins/channels/qq_obv11/ratelimit.go
T

53 lines
1.3 KiB
Go

package qq_obv11
// This file implements the sliding-window send rate limiter that keeps QQ
// OneBot proactive/reply traffic from bursting (see DevDocs/design/08 section
// 3, "注意风控").
import (
"errors"
"sync"
"time"
)
// ErrRateLimited is returned by SendMessage/SendProactive when the configured
// per-window send quota is exhausted.
var ErrRateLimited = errors.New("qq-obv11: send rate limit exceeded")
// rateLimiter enforces a maximum number of events within a sliding window. It
// is disabled when max is non-positive.
type rateLimiter struct {
max int
window time.Duration
mu sync.Mutex
times []time.Time
}
func newRateLimiter(max int, window time.Duration) *rateLimiter {
return &rateLimiter{max: max, window: window}
}
// allow records a send at now and reports whether it fits within the window
// quota. A disabled limiter (max <= 0) always allows. The timestamp is only
// recorded when the send is accepted.
func (r *rateLimiter) allow(now time.Time) bool {
if r == nil || r.max <= 0 {
return true
}
r.mu.Lock()
defer r.mu.Unlock()
cutoff := now.Add(-r.window)
i := 0
for i < len(r.times) && !r.times[i].After(cutoff) {
i++
}
r.times = r.times[i:]
if len(r.times) >= r.max {
return false
}
r.times = append(r.times, now)
return true
}